Solved

Make Second Form as Main

Posted on 2006-07-17
31
298 Views
Last Modified: 2010-04-05
Hello everyone,

I created a project and then decided to add another form and make it as the main one. The thing is that when I run the project, both forms pop up. I tried hiding the form that I want to be the second one so it pops up on button click of the other form. However, the second form flashes when I run the application.

Can anyone help me make the second form created as the main form and that it will be the only form that pops up on running the application?

Regards
King_Diamond
0
Comment
Question by:King_Diamond
  • 16
  • 11
  • 2
  • +2
31 Comments
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17125231
Check the project sources first, originally it probably looked like:

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1); // Main form
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

then it should have been changed to:

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm2, Form2); // Make 2nd form the main
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

And make sure you are not calling .Visible:=True, ShowWindow(Handle) or similar in the form creation logic of the first form (that was originally the main form).

Regards,
Russell

0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17125273
It is how I did it and that is why both forms are popping up. All forms (7 till now) are set to visible:=true but only the first 2 pop up.
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17125304
I set the second form visible:= false and true on button click and it seems ok. Is this the correct way to do it? I mean, ain't there a way to replace the first form (main) with the second one?
0
 
LVL 4

Expert Comment

by:LMuadDIb
ID: 17125354
goto the menu and select "Project/Options" then the Forms tab
adjust the "main form"
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17125356

That is correct. (regarding the other forms, are they set to Auto Create?; i would be willing to venture that they are not)

Normally, the form's visible property should be set to false. For the mainform, the Application will set the main form's visible property to true during the Application.Run method UNLESS the Aplpication.ShowMainForm property is set to false.

RUssell

0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17125359
The thing is that it looks ackward as every time I go from one form to another at run time, the application window in the taskbar, closes and opens another again. It does not stay in the taskbar like when the forms are created in "normal order".
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17125404
LMuadDIb,

The main form in the project options is set correctly.

rllibby,

I am no delphi expert. Can you please explain what you mean with set to Auto Create?
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17125439
rllibby,

Ok I found the auto create and yes you were right, however I moved them to available forms except for the main form and the application crashed with an error EAccessViolation.
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17125466

You need to watch where you call things. If only the main form is in the auto create list, and the main form attempts to access the second form without creatng the secondary form, eg:

FormVariable:=TSecondaryForm.Create(Self);

Then you will get an access violation. When the form is in the available list, its class definition is available, but there is no runtime instance created.

Russell

0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17125532
Ok, understood. However the main form is in the auto create but it crashes before the main form is visible. Hence I think that it is still trying to load the other form which previously was the main form, am i right?
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17125639

It would help if you pasted the project source (like I did above) so I have a point of reference on this;  But without seeing anything, I would say to check the FormCreate logic for what is now your main form, and ensure that it is not attempting to access other forms (without first creating them)

Russell

0
 
LVL 5

Expert Comment

by:Scay7
ID: 17125720
try doing this without changing the :

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1); // Main form
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

and in the form2 code window... do this

var
  Form2: TForm2;

implementation

uses Unit1;

{$R *.dfm}

procedure TForm2.FormCreate(Sender: TObject);
begin
form2.Visible := true;
end;

procedure TForm2.FormPaint(Sender: TObject);
begin
form1.Visible := false;
end;


All this does is let the window create themselfs inorder as they were made and you simply hide the form1 after form2 has finished painting... there by making form2 your main window... but beware if you close form2 you need to make a procedure for the ondestroy in form2 to close form1 there by closing the entire application if thats what you want or when form2 is close use the same ondestroy method to make the next form visible...

Peace Scay7 :P
0
 

Expert Comment

by:monitorwa
ID: 17127454
Im not sure about making the second form the "main" form, without changing the options under projects. You can make the second form the only one to appear by adding

 Application.Initialize;
Application.ShowMainForm := False;

  Application.CreateForm(TForm1, Form1); // Main form
  Application.CreateForm(TForm2, Form2);
  Application.Run;
To the program definition page. You'll still need to add an OnClose option to form 2, otherwise the program will keep running with a hidden main form in the background.
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17133014
Scay 7,

If I do Form2.Visible := False, it solves the problem however, the minimized window in the taskbar is closed with the form and re-created with each form. I guess it is personal taste but I would prefer it to stay there as it seems like the application has closed and run again.


monitorwa,

I tried your suggestion but it skipped form 1 and 2 and the first form visible is form 3!


rllibby,

Here is the project source up to now.

program Connection;

uses
  Forms,
  Splash in 'Splash.pas' {SplashScreen},
  Unit_Password in 'Unit_Password.pas' {Login},
  Unit_CheckConnection in 'Unit_CheckConnection.pas' {Connection},

{$R *.res}

begin
  Application.Initialize;
  Application.Title := 'Connection';
  Application.CreateForm(TLogin, Login);
  Application.CreateForm(TConnection, Connection);
  Application.Run;
end.
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17133317

Makes a little more sense. First, the application's main form should be the form that controls operation of the application (more specifically, the one that when closed will end the application). In the snippet above, the login form becomes the main form, which is probably not a good idea. It would be better to arrange it like this:

program Connection;

uses
  Forms,
  Splash in 'Splash.pas' {SplashScreen},
  Unit_Password in 'Unit_Password.pas' {Login},
  Unit_CheckConnection in 'Unit_CheckConnection.pas' {Connection},

{$R *.res}

begin
  Application.Initialize;
  Application.Title := 'Connection';
  Application.CreateForm(TConnection, Connection);
  Application.CreateForm(TLogin, Login);
  Application.ShowMainForm:=False;
  Login.Visible:=True;
  Application.Run;
end.


Then in your login form, handle the form close one of two ways. If the user fails to login, call Connection.Close to close the main form (currently hidden) and to close the application, or to make it visible and allow the user to do whatever it is they do with your application. eg:


var
  LoggedIn:      Boolean;
  LoginForm:     TLoginForm;

implementation
uses    'Unit_CheckConnection';
{$R *.DFM}

procedure TLoginForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin

  if LoggedIn then
     MainForm.Visible:=True
  else
     MainForm.Close;
 
end;




0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 26

Expert Comment

by:Russell Libby
ID: 17133356
That is, assuming the login form needs to occur before the main form? (which one is the LOGICAL main form from the user's perspective?)

Russell
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17133679
I tried your code but like this, after the splash screen, the Connection form is popping up but not the login form. It's the opposite of what I need.
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17133689
Btw, your assumption is correct.
0
 
LVL 5

Expert Comment

by:Scay7
ID: 17134068
King_Diamond what in form2 is dependent in form1...

What i mean is what is set or created in form1, that it needs to be made first before form2 can be made ?

Mabey the solution to this is to copy or change form1 to form2 and visa versa ?

Peace Scay7
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17134100

King_Diamond,

The problem is that we have little context for what you are doing, and what dependencies exist between the multiple forms. The only way to get this solved without placing an inordinate burden on either us or you would be for you to do the following:

- create a small application that duplicates the problem you are having, The forms can be empty of controls, just so long as the problem can be duplicated.
- Mark each form's caption with text indicating the order is should be in, and also which one is to be the main
- copy the source for the project and each form here

Anything else is just guesswork.

Russell
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17136691
Scay7,

I think that is a good idea but guess it takes lots of work to replicate the forms unless there is a simple way that I don't know of.


Russell,
 
I presently don't have delphi application installed on this pc and hence I can't duplicate the problem. However it's no problem to do it later.

In simple words, I created an application which I later added a login form. It stands to reason that the user has to login before the main form is visible and hence i want the login form to be visible prior to the main form. Hope this explains what happened.
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17139096
Seems I found the problem.

In the "new" main form, I added the following code for the splash screen.

  SplashScreen := TSplashScreen.Create(Application);
    try
      SplashScreen.Show;
      Application.Initialize;
      SplashScreen.Update;
      Sleep(5000);
      SplashScreen.Hide;
    finally
     SplashScreen.Free;
    end;
     Application.Run;

If I remove the SplashScreen.Hide and SplashScreen.Free, the problem is solved. However then, the splash screen stays on. Is there something wrong with my code?

Russell,

I tried to replicate the problem but no luck! If I try a new application, it works fine!
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17139175
Please tell me you not doing

>>  Application.Initialize;
>> Application.Run

in any place other than the project source...

Russell
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17141025
Yes in the new form I created, why?

Is there something wrong?
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17141142

It is a bit of a faux pas, as the only place either of those methods should get called is in the project source, and even then, they should not be called more than once. This is what causes the task bar item to disappear and reappear again. (which it normally would not do)

Your code should be more along the lines of:

  SplashScreen:=TSplashScreen.Create(Self);
  try
     SplashScreen.Show;
     SplashScreen.Update;
     Sleep(5000);
     SplashScreen.Hide;
  finally
     SplashScreen.Release;
  end;


Russell

0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17141277
I tried your suggestion but same result. It works fine if I remove the SplashScreen.Hide and SplashScreen.Release but then the SplashScreen does not close. I tried SplashScreen.Close but same result.
0
 
LVL 26

Accepted Solution

by:
Russell Libby earned 50 total points
ID: 17141974

King_Diamond,

I am posting one final example for you. I say final, because after 9 posts I still have yet to see the full context (code/dfm) of your application. Hopefully you will find this example useful in resolving your issue.

Best of luck,
Russell


program Example;

uses
  Windows,
  Forms,
  Controls,
  Main        in 'Main.pas' {MainForm},
  Login       in 'Login.pas' {LoginForm},
  Splash      in 'Splash.pas' {SplashForm};

{$R *.RES}

begin

  // Intialize the application
  Application.Initialize;

  // Create all three forms
  Application.CreateForm(TMainForm, MainForm);
  Application.CreateForm(TLoginForm, LoginForm);
  Application.CreateForm(TSplashForm, SplashForm);

  // Show application window (nothing but the tray image for the app). We do this
  // so that as we show / hide windows, we dont get the effect of our app appearing and
  // disappearing on the task bar.
  ShowWindow(Application.Handle, SW_SHOWNORMAL);

  // Start with the splash screen which will close itself after 5 seconds (using a timer)
  SplashForm.ShowModal;

  // Now run the login form. If the OK button is clicked, the application will
  // continue to the main form. If cancel is clicked, the application is ended
  if (LoginForm.ShowModal = mrOK) then
  begin
     // Run the main message loop
     Application.Run;
  end;

end.

----------------------------------------------------------------------------------------------

--- Main ---
unit Main;

interface

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

type
  TMainForm         =  class(TForm)
     Label1:        TLabel;
  private
     // Private declarations
  public
     // Public declarations
  end;

var
  MainForm:         TMainForm;

implementation
{$R *.DFM}

end.

--- Main DFM ---
object MainForm: TMainForm
  Left = 305
  Top = 184
  Width = 582
  Height = 360
  Caption = 'Main Form'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesktopCenter
  Scaled = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 0
    Top = 0
    Width = 574
    Height = 232
    Align = alTop
    Alignment = taCenter
    Caption = 'This is the main form'
    Font.Charset = ANSI_CHARSET
    Font.Color = clWindowText
    Font.Height = -96
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    Transparent = True
    WordWrap = True
  end
end

----------------------------------------------------------------------------------------------

--- Login ---
unit Login;

interface

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

type
  TLoginForm        = class(TForm)
     Label1:        TLabel;
     Button1:       TButton;
     Button2:       TButton;
  private
     // Private declarations
  public
     // Public declarations
  end;

var
  LoginForm:        TLoginForm;

implementation
{$R *.DFM}

end.

--- Login DFM ---
object LoginForm: TLoginForm
  Left = 283
  Top = 267
  BorderIcons = [biSystemMenu]
  BorderStyle = bsDialog
  Caption = 'Login Form'
  ClientHeight = 277
  ClientWidth = 538
  Color = clBtnFace
  Font.Charset = ANSI_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = [fsBold]
  OldCreateOrder = False
  Position = poScreenCenter
  Scaled = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 0
    Top = 0
    Width = 538
    Height = 232
    Align = alTop
    Alignment = taCenter
    Caption = 'This is the login form'
    Font.Charset = ANSI_CHARSET
    Font.Color = clWindowText
    Font.Height = -96
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    Transparent = True
    WordWrap = True
  end
  object Button1: TButton
    Left = 368
    Top = 244
    Width = 77
    Height = 25
    Caption = 'OK'
    ModalResult = 1
    TabOrder = 0
  end
  object Button2: TButton
    Left = 448
    Top = 244
    Width = 77
    Height = 25
    Caption = 'Cancel'
    ModalResult = 2
    TabOrder = 1
  end
end

----------------------------------------------------------------------------------------------

--- Splash ---
unit Splash;

interface

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

type
  TSplashForm       =  class(TForm)
     Label1:        TLabel;
     Timer1:        TTimer;
     procedure      Timer1Timer(Sender: TObject);
     procedure      FormShow(Sender: TObject);
  private
     // Private declarations
  public
     // Public declarations
  end;

var
  SplashForm:       TSplashForm;

implementation
{$R *.DFM}

procedure TSplashForm.Timer1Timer(Sender: TObject);
begin

  // Close the splash screen form
  ModalResult:=mrOK;

end;

procedure TSplashForm.FormShow(Sender: TObject);
begin

  // Enable the timer
  Timer1.Enabled:=True;
 
end;

end.

--- Splash DFM ---
object SplashForm: TSplashForm
  Left = 355
  Top = 155
  BorderIcons = []
  BorderStyle = bsDialog
  Caption = 'Splash Screen'
  ClientHeight = 480
  ClientWidth = 408
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  Position = poScreenCenter
  Scaled = False
  OnCreate = FormCreate
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 0
    Top = 0
    Width = 408
    Height = 464
    Align = alTop
    Alignment = taCenter
    Caption = 'This is the splash screen'
    Font.Charset = ANSI_CHARSET
    Font.Color = clWindowText
    Font.Height = -96
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    Transparent = True
    WordWrap = True
  end
  object Timer1: TTimer
    Enabled = False
    Interval = 5000
    OnTimer = Timer1Timer
    Left = 8
    Top = 8
  end
end

0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17148283
Russell,

Thanks for your detailed reply. However the problem remains. On the other hand, I managed to replicate the problem.

I opened a new application and added a second form. On form 1, I dropped a button and here is the code for unit1.
----------------------------------------------------------------------------------------------------
unit Unit1;

interface

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

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

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form1.Hide;
  Form1.Free;
  Form2.Show;
end;

end.
--------------------------------------------------------------------------------------------------
I did nothing else, just ran the problem and there is the problem. Hope this helps.
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17159573
It seems that when I hide a form, the application looks like closing and re-opening in the taskbar. I tried .....

Form1.Hide;
Form1.Free;
Form1.Visible := False;

All same result. I also tried Form1.Close but this is closing the application (acting like Application.Terminate).

Anyone has any ideas pls?
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17159899

I already gave you the answer to that problem in my last posting (re-check the project source), but I doubt you even bothered to look at it....

 // Show application window (nothing but the tray image for the app). We do this
  // so that as we show / hide windows, we dont get the effect of our app appearing and
  // disappearing on the task bar.
  ShowWindow(Application.Handle, SW_SHOWNORMAL);

Does that look familiar??
0
 
LVL 1

Author Comment

by:King_Diamond
ID: 17161238
rllibby,

It works. I did try your code but I guess I put it in the unit instead of the project source. I guess I was half asleep when I tried it lol.

Thanks a lot for your help.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now