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

Working with splash screen from other form 1

Status
Not open for further replies.

djjd47130

Programmer
Nov 1, 2010
480
US
An app of mine creates a splash screen during app initialization, and it's free'd before even the main screen is shown. Has to be manually created this way. However, from the main screen, as I'm doing the loading, I want to post a status to this splash screen (somehow send just a string to it). Since it's manually created in the application source (not the form unit), I cannot access it. How can I just send some data to this screen?

For example, from the main form while I load, I want to post some data to the splash screen like:

Code:
procedure TForm1.PostToSplash(const Status: String; const Progress, ProgressMax: Integer);
begin
  //Send 'Status', 'Progress', and 'ProgressMax' to splash screen to update

end;


JD Solutions
 
I'd try rigging a message to the window handle of this form and then send my information through the message and let the other form respond to it. Whether it would work or not on a supplemental form is another story, but that would be my first thought.

Code:
const
  WM_LVUPDATE = WM_USER + $1004;

procedure TSha1Rename.MessageAdd(MsgValue: String);
// posts a message to the memo box
begin
  SendMessage(WinHandle, WM_LVUPDATE, 0, Longint(PChar(MsgValue)) );
end;

And in the form:
Code:
type
  TfrmFileCheck = class(TForm)
  protected
     procedure LVUpdate(var WinMsg: TMessage); message WM_LVUPDATE;
  end;

procedure TfrmFileCheck.LVUpdate(var WinMsg: TMessage);
begin
  MessageMemo.Lines.Add(String(PChar(WinMsg.LParam)));
end;

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
A simple approach is to add a class procedure to your splash form, that can be called from your .dpr file..

To do so, in the .dpr file add the code to create the splash form.

Remove the splash form from the autocreate list, but make sure the form's unit is still in the uses list..

uses
...
splash in 'splash.pas' {Splash_Form},
...;

Assuming the Form's name is Splash_Form...
Code:
var
   S:  string;

Splash_Form := TSplash_Form.Create(nil);
//you do not have to declare Splash_Form 
//use the form's name as variable name
try
   Splash_Form.Show;
   While <still processing> do
   begin
      //do your processing here
      S := <status string>;
      Splash_Form.UpdateStatus(S);
      Splash_Form.Update;
   end;
   finally
      Splash_Form.Free;
   end;
   Application.Initialize;
   Application.MainFormOnTaskbar := True;
   Application.CreateForm(TMain_Form, Main_Form);
   Application.Run;
end.

Then declare the class procedure within your splash form
Code:
type
  TSplash_Form = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
    class procedure UpdateStatus(S: string);
  end;

class procedure TSplash_Form.UpdateStatus(S: string);
var
   F:  TSplash_Form;
   I: Integer;
begin
   F := nil;
   For I := 0 to Screen.FormCount - 1 do
      //cycle through all the forms
      if (Screen.Forms[I] is TSplash_Form) then
         //test to see if its your splash form
         F := Screen.Forms[I] As TSplash_Form;
           //if it is, set F to point to it.
   if F <> nil then
      //if F is not nil, you found the form
      F.Caption := S;
        //in this case, it sets the form's caption
end;
 
Re-red your problem, saw that you want to be able to update the splash form from your main form, so this approach will still work, but you'll need to make a few modifications to make it work that way.

your project's .dpr will now look like this:

Code:
uses
  ...
  splash in 'splash.pas' {Splash_Form};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Splash_Form := TSplash_Form.Create(nil);
  try
     Splash_Form.Show;
     Application.CreateForm(TMain_Form, Main_Form);
     //make sure you create your main form after you create
     //your splash form...
  finally
     Splash_Form.Free;
  end;
  Application.Run;
end.

Then your main form's oncreate you can now call the splash form's class procedure (which does not need to change)

Code:
procedure TMain_Form.FormCreate(Sender: TObject);
var
   S: String;
begin
   while <still processing> do
   begin
      S := <Status>;
      Splash_Form.UpdateStatus(S);
      Splash_Form.Update;
   end;
end;
 
I don't understand all the fuzz.
Create your splashform in the OnCreate event of your main form and it's accessible. The above solutions are valid though but it's a bit clumsy and really not needed.

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thanks for the input, but I already have the splash screen creation coded, that's not a problem. Just the sending messages part was all I needed to know. Also, there's a number of other checks in the project file between the time the splash screen is made and the main form is created. If certain checks fail, the main form is never created at all and the application terminates. The main form is just one of the things which takes time to load, thus requiring use of the same splash screen.

JD Solutions
 
Doing some investigation, the method of sending messages did not work. I forgot there's two places I can put the unit in the uses - I moved 'uSplash' from the interface to the implementation of the main form - then I can access it accordingly. Just have to make sure it is in fact created before trying to do anything with it.

JD Solutions
 
The main form is just one of the things which takes time to load, thus requiring use of the same splash screen

that's my point. The main form is the main entry point.

pseudo FormCreate code:

Code:
procedure TForm1.FormCreate(Sender: TObject);

var Splash : TSplashForm;

begin
 if not CheckIfWeCanContinue then
  begin
   Application.Terminate;
   Exit;
  end;
 Splash := TSplashForm.Create(nil);
 try 
  Splash.Show;
  DoTimeConsumingLoad; 
 finally
  FreeAndNil(Splash);
 end;
end;

No need to mess with the application source and you get the same result...

/Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thanks whosrdaddy, but the way this app works already depends on how the project file starts. It may never create any form at all, other than the splash screen. To put it another way, I may have reason to create another form rather than the main form. The main form is very massive, and I don't want it to even create unless it has to. If the checks conclude that the application is not supposed to run, then it never creates the main form (thus doesn't create all the VCL components on this form or anything). Also, supposing the app fails to connect to the database, it needs to create another intermediate form instead of the main form, which collects the necessary connection info from the user. I have my reasons, this project already has a lot in the project source and I'm not going to move it, I put it in there for a reason. Now I need to work around what I already have.

Thanks for the input though, always of course appreciated.

JD Solutions
 
Ok - I see now.

Cheers,
Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
One more small modification to the updatestatus class procedure

Change
Code:
if (Screen.Forms[I] is TSplash_Form) then
   F := Screen.Forms[I] As TSplash_Form;
to
Code:
if (Screen.Forms[I] is TSplash_Form) then
begin
   F := Screen.Forms[I] As TSplash_Form;
   Break;
end;
that way, once it found the form, it doesn't continue searching...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top