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

Ideas for a Splash Screen?

Status
Not open for further replies.

David Higgs

Programmer
May 6, 2012
390
GB
Looking for some ideas on how to provide a "Splash Screen" for my application(s) whilst it's initialising. Nothing too fussy, just a message showing that the program is running. My main form Logbook.SCX is currently a 'Modeless', 'Top Level Form'.

Code:
*                      
*	Display Main Form  
*	-----------------  
		
DO FORM Logbook WITH tcCallsign

READ EVENTS

Regards,

David

Recreational Developer and End User of VFP for my personal use in 'Amateur Radio' and 'British Railways' related Applications.
 
Well, put a timer on another top-level form like Logbook is and in the timer event put Thisform.Release().

Chriss
 
Isn't there a snag there, the screen might be visible and timed, but the app won't finish setting up
until the splash goes away...

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
No, as the application has a top level form and I suggested making the splash screen another top level form, which are non-modal form, always, there is no blocking. It can be in front with alwaysontop =.t. and the normal main form also already can starts while the splash screen shows. So no, nothing is blocked, but the view to the normal main form. Any other normal initialization also is done. The splash screen removes itself after the timer interval or when the user closes it, that's all to it.

Chriss
 
I don't agree with the form having a timer.

But it depends on why you want the splash screen.

If the app is going to take more than a couple of seconds to load, then a splash screen is a good idea, as it gives the user some visual feedback during the loading. But in that case you want the splash screen to disappear as soon as you are ready to show the main form. A timer wouldn't work, because you don't know in advance how long the app will take to initialise. If the time interval is too low, there will appear to be a delay before the main form opens. If the time interval is too high, the main form will open while the splash screen is still visible. Neither is desirable.

So what you need is to close the splash screen explicitly:

Code:
DO FORM "Splash" NAME oSplash

* Stuff here to initialise the app (opening tables, etc).

oSplash.Release
DO FORM Logbook WITH tcCallsign

If, on the other hand, the app loads more or less instantly, you might still want a splash screen to provide a sort of welcome to the user. In that case, you can decide in advance how long it should remain on the screen. Although a timer would work for that, it would be simpler to control the timing within the main program:

Code:
DECLARE Sleep IN WIN32API INTEGER
DO FORM "Splash"
Sleep(2000)   && Show splash screen for 2 seconds)
oSplash.Release
DO FORM Logbook WITH tcCallsign

Obviously, for all this to work, the splash screen has to be modeless, but as it is a top-level form, that will always be the case.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well,

and I don't use a splash screen to load and initialize stuff. That also usually takes less time than you need to see the logo for me, but you might do more than setting procedures and libraries. Checking all table health states, for example, or loading much data, which I don't like to do.

Any way you do it this can be done in parallel to a splash screen too, if that's non-modal, and for the third time: I say this is non-modal in my recommendation. No matter how you initialize your application before you addded a splash screen, you stick to it the way it was and stays and is. And the splash screen is really just that - a splash screen only, like that:

main.prg:
Code:
LPARAMETERS ... && if yo had some parameters in yor main.prg, it has to stay the first line
DO FORM spalshscreen && non-modal, toplevel form set alwaysontop=.t. with a timer releasing it, if the user doesn't close it first.
* it does nothing but display a splash image and then can have a timer to release it and the user can close it even beforehand. 
* Because there is nothing going on in the splash screen there's no need to hinder the user from closing it, too.

* Rest of the code as it was, with initialization and adding a menu and mainform or whatever your application needs and does
* IMPORTANT: [highlight #FCE94F]This already runs while the splash screen form shows as that form is non-modal[/highlight].

There also is the possibility to start an EXE with the command line option -BFileName,Duration
But that's a bad option, as it merely displays an image and pauses for the specified duration, only after that your EXE really starts. With a non-modal spalsh screen there is neither blocking, nor does it need to stay open as long as the initialization takes because this initialization does not need to be integrated into the splash screen form.

I take it for granted you both know what modal and non-modal form means,, so I don't understand your criticism at all, it's nonsensical. I can understand, Mike, that you might want to keep the splash screen open, when you integrate the intiailization phase into it, but again, you don't have to and I didn't recommend doing so. If you do, of course closng the spalsh screen before the intialization phase is over would even harm the start. I also understand you may integrate these two things together, so the splash screen is more than just a splash screen, but also shows progress of intiallization, like phases of checking database file health, loading initial data and whatever else your complex intialization takes.

But a splash screen running for 3 seconds can close while the initialization still runs, it does not interrupt the initiallization, if it stays where it was, in the main.prg or in the main form your main.prg runs or in procdedures, in an application class init and in any other way, because the spalsh screen I suggested is just a toplevel non-modal form with a tier releasing it, it has nothing else to do nor does it hinder anything else to run, nor does its release interrupt anything else running.

I don't know along which lines you think about my solution, but both of your criticisms is harmful in my eyes, as you make people think it really does not work the way I suggest it. Non-modal forms are not blocking, Griff, and a form only displaying an image is also not immportant to stay open longer than the user needs to see it and he can close it, Mike. A timer also isn't blocking the execution of further code, but only interrupts it after the timer interval for the release of the splash screen form, which takes split seconds. So your initialization time does stay as it was. Initialization may take less time than the interval of the splash screen timer, so your main form appears already while the splash screen still shows, but that's also not immportant, as the user can close the splash screen and the splash screen also automatically closes, which should be done in an interval long enough to recognize the splash screen, say 3-5 seconds or 3000-5000 ms as the timer interval is set in milliseconds. And not to forget, the main screen also will show up behind the splash screen, as I recommended to set alwaysontop=.t. in it. And this setting does not make it the overall desktop foreground, but its on top of every other form of your application not having that property set .t., so it sticks to the front of your main form, if that shows quickly anyway.

What you do in intialization once to speed up the application usage in general, that's a separate topic, I'm not really a fan of such optimizations as a long initiallization phase sometimes makes me think twice, if I use that application. For example I use gimp, but if I can manage to process an image with MSPaints limited fnctionality I may prefer it, as it starts much quicker. The gimp splash screen showing progress of what it's doing isn't making this better. I do like Gimp, as it has so many more features and it pays to start it, but not always. So if a long intialization is your eason for a splash screen, then think twice about what in the initialization really is necessary, some things could be done only one day of the week, for example, others can be done when you actually start the form or featre that needs it and not beforehand already. And then there are optimizations that could be done to improve connecting to a remote server or database, talk to the reponsible persons about that, don't just accept it takes some time.

Chriss
 
And David,

of course you may still do as Mike suggests, but his and Griffs idea that a splash screen does the initialization is nothing you have to do.
So what Griff says...
GriffMG said:
but the app won't finish setting up
until the splash goes away..
...and what Mike says...
Mike Lewis said:
A timer wouldn't work, because you don't know in advance how long the app will take to initialise
Only is true if the initilaization code is within the splash screen and the timer releases the form before that finishes.

Both of these are not true, if the initializaiton stays where it was before introducing the splash screen. There is no rule telling that you have to move initialization code into a splash screen and by no means does it have to be done that way only to work.

Chriss
 
To give you a concrete example of a splash form as I see fit for your application, here is your new full main.prg:

Code:
Lparameters tcCallsign && assumed from your DO FORM statement

*                      
*	Display Splashscreen
*	----------------- 
Local loSplash
loSplash = CreateObject("Splashscreen")
loSplash.Show()

*                      
*	Display Main Form  
*	-----------------
DO FORM Logbook WITH tcCallsign
READ EVENTS 

Define Class SplashScreen as Form
   ShowWindow = 2
   AlwaysOnTop = .t.

   Add object timer1 as splashtimer
   
   Add object image1 as Image
      image1.Top = 0
      image1.Left = 0
      image1.Picture = Home()+"fox.png"

   Procedure Init()
      This.Width = This.image1.Width
      This.Height = This.image1.Height
   Endproc
EndDefine

Define Class Splashtimer as Timer
   Interval=3000
   Enabled = .T.

   Procedure Timer()
      Thisform.Release()      
   Endproc
Enddefine

If anything your application needs is to start the Logbook form, that stays that way, there's nothing to move into the splash screen or between starting the splash screen and starting your Logbook form.
And if you create a SplashScreen.SCX, instead of the prg class I used here - just as it's easier to post in a forum - you can simply do

Code:
Lparameters tcCallsign && assumed from your DO FORM statement
*                      
*	Display Splash Screen
*	-----------------  		
Do Form splashscreen

*                      
*	Display Main Form  
*	-----------------  		
DO FORM Logbook WITH tcCallsign
READ EVENTS

It's as simple as that, because you create the splasscreen.scx like you created yot logbook form, as toplevel (ShowWindow=2) and set its alwaysontop. The init code just sizes the form as large as the splash image is, and then sets autocenter=.t., because then the form has the size that is the basis for cetnering it.

You could also set image anchoring so the image sizes to the form size, or you can put anything else on your splashscreen.

And you can display and do anything else in your splashscreen, it doesn't have to be just an image, of course.

Chriss
 
I've set up a 'Top Level' and 'Modaless form' with a timer.

When I run my app a Blank Form appears and then a message saying "Executing remote", after a short delay the form is then populated and another "Executing remote" message appears before my app main form appears.

In my main.prg I have LPARAMETERS as the first line etc and then set up the 'Paths' before launching the 'Splash Screen' and continuing setting up MySQL connections etc. The same applies with your sample code 'splashscreen'.

Regards,

David

Recreational Developer and End User of VFP for my personal use in 'Amateur Radio' and 'British Railways' related Applications.
 
David, did you see my comments (above) with my reasons for not using a timer? I hate to cross swords with Chris on this issue, but I think my approach is worth considering.

It would help to know what exactly is your goal with this splash screen. Are you doing it because the app might take several seconds to load, and you want to give the user some reassurance that something is happening during that time? Or is it for purposes of "branding: to display a logo or welcoming message of some kind, rather than going straight to your user interface?

Both reasons are equally valid, but they call for a different approach.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hello Mike,

Mike Lewis said:
It would help to know what exactly is your goal with this splash screen. Are you doing it because the app might take several seconds to load, and you want to give the user some reassurance that something is happening during that time? Or is it for purposes of "branding: to display a logo or welcoming message of some kind, rather than going straight to your user interface?

The reason for the splash screen is to give me reassurance the application is running. As with all of my apps, I am the 'end user'.

I did try removing the Timer, although it appeared to make no noticeable difference.

Regards,

David

Recreational Developer and End User of VFP for my personal use in 'Amateur Radio' and 'British Railways' related Applications.
 
Mike, it's not the timer that's causing the problem.

David, I don't know what you mean with ""Executing remote", it's not a native FoxPro error message.

Mainly you just do a splashscreen with alwaysontop=.t. right before doing your mainform. In turn the splashscreen shows up first and even if the mainform shows up before the timer finishes, it shows up behind the splash screen. Any messages you see about your application won't come from the new splashscreen form, unless you put a lot of unnecessary code into it. By saying you should do the splash screen just like your logbook main form, I don't mean to copy the logbook. Just start with a new empty form, and set it ShowWindow=2 and AlwaysOnTop=2, that's the two major things to do in it. It then is a modeless toplevel form. No more, no less.

Anything else is optional, even the timer, but likely you want to show a picture and likely you want the classic splash screen behavior to go away without the user needing to click the close button. The timer is just there to release the form even if the user does not do anything.

Mike and also Griff seem to have a fixed association with the splash screen to signal the user now everything is ready to be used. I just think like you, David, the major purpose of the splash screen just is there to show the application has started, so you don't double-click the exe more than once, just because you get no visual feedback. So the splash screen should not need any initialization and start as soon as the exe runs and it's also not necessarily there to show progress of initialization. It can, but that's not its main purpose. Last but not least, it does not need to release when the initialization is ready, nor does it need to stay visible, if the initialization still needs time. You already have the signal the EXE is started and you will be able to use the main form. That's the whole purpose, and any further purpose is actually made up by your own ideas of what a splash screen must be, Mike and Griff. I disagree, still disagree and I gave an easy to verify code example how that works.

Chriss
 
And David, if your own impatience is your main problem, you starting the EXE more than once, also causing connection problems with MySQL and what else that might cause, there are rigorous ways for an EXE to first check it does not run itself. Then you should rather implement such a mechanism than a splash screen.

On a very busy computer - and you never know what the OS does - it can take a second or a few before you see something from an EXE you start, may it just be an EXE that only shows the _screen and does nothing but READ EVENTS. So a splash screen also won't come up just as soon as you double-click.

I have lately tried Avast antivirus, and it's a nightmare for any developer: If you run a newly built EXE the first thing Avast does is stop it, then Avast reports a threat, scans the EXE, and then eventually likely reports no problem and restarts the EXE. That can really disturb your development cycle. Maybe it's also such an antivirus mechanism that causes the start of an EXE to delay and not give early feedback to you that you actually started.

If a double click becomes a problem for you, you can also use the right click and "open". It's giving the visual feedback the context menu disappears, and you can be sure the EXE has started, even if nothing shows up immediately. Your own influence about this ends, when the first step of your main.prg is showing a form (like the splash screen). There's something going on before that, the VFP runtime loads and foxuser.dbf is read or created, those things are all done before your first line of code and you don't have any influence on how long that takes. Other than putting your EXE on a fast hard drive, SSD or loading it into a RAM disk, you can't specify how fast the EXE stub starting up a VFP exe takes.

Chriss
 
Chris Miller said:
David, I don't know what you mean with "Executing remote", it's not a native FoxPro error message.

When I run my App I see a small pop window that says "Executing remote - Press Escape to Cancel". This is possibly a windows system message, whatever it is, it stops the form from displaying correctly until the above message disappears. The Form is very basic just a 'Please Wait' Label and change of the back colour. So I don't know why there is a pause before the back colour changes and the label is displayed.

Regards,

David

Recreational Developer and End User of VFP for my personal use in 'Amateur Radio' and 'British Railways' related Applications.
 
Well, David, you have to find out where that comes from, I don't know it.

Chriss
 
Chris Miller said:
Well, David, you have to find out where that comes from, I don't know it.

Maybe due to connecting to MySQL Server (MariaDB) I'll do some further tests.

Regards,

David

Recreational Developer and End User of VFP for my personal use in 'Amateur Radio' and 'British Railways' related Applications.
 
David,

David Higgs said:
Maybe due to connecting to MySQL Server

Well, you do that, it's not the VFP runtime. As you don't have initialization code in the main.prg, it must be in the load and init of the Logbook form, and in its dataenvironment, if you use a connection and a DBC with remote views to MySQL. That also "runs" before the Logbook form shows when you DO FORM Logbook.

But before you start Logbook you now start the Splashscreen form, don't you? You haven't copied it to let it have the same properties and do all the stuff in the data environment, do you?
Just do your splash screen from scratch and set ShowWindow=2 and AlwaysOnTop=.T., size it properly, put an image on it... Whatever you want as the splash screen. But don't have anything in its data environment that causes it to connect to MySQL and load data from there or whatever else, it shouldn't do anything but show up as fast as possible after the EXE is started, right? And whatever else is needed was and is done in Logbook, there is no need to shuffle that around. The splash form being ShowWindow=2 and AlwaysOnTop =.T. means it shows up no matter if SCREEN=ON or SCREEN=OFF, it shows up on top of even other top level forms and code execution continues immediately after it shows.

Both forms show, the one READ EVENTS after DO FORM Logbook keeps them both "alive".

In essence, you really only need to add one DO FORM, and that form has to be non-modal and top-level and alwasontop=.t. and a timer (optional) for automatic release and that's it. I don't know why this takes so many tries.
The name splash comes from it being there as immediately as possible, it splashess up, right when you start an EXE. You can move initialization of MySQL connection etc. into it later, but just start with a dumb splash screen that does nothing. You already have all you need in the rest of your project, the code and the forms, there is no need to modify that in step 1 of introducing a splash screen. There's not even the need to do that as next step.

Chriss
 
Hi,

I’m using a splash screen, called from my main form. In the splash screent’s activate event I do all sorts of things, I connect to MySQL, I check for all tables if all fields are available (and add/delete fields when necessary), I read my application’s setup values from MySQL and I read my user’s personal settings from MySQL.

I read always from MySQL into a VFP cursor and disconnect immediately, there is never a permanent MySQL connection. I close every cursor when it’s no longer needed. All for speed, reliability and simplicity.

I have a timer starting in the splash form’s init and when the activate event is finished I check the timer once again and determine if it’s time to release the splash screen.

I didn’t want to use a splash screen without it being functional too. That’s a waste of time.

Regards, Gerrit
 
Is it a waste of time?

David has well described why he wants to have a splash screen:
David Higgs said:
...just a message showing that the program is running

Besides that, the way I constructed the splash screen it shows for timer.interval milliseconds, but it doesn't stop or pause execution for that time, whatever else runs and still runs with the splash screen present takes the same time. How often do I need to point that out until it sinks in? The splash screen I suppose to create is a [highlight #FCE94F]non-modal[/highlight] form. The only time lag it causes is the time needed to create and show it and the time needed to release it. And that's less than a millisecond all-in-all.

What is so difficult to understand about this?

That splash screen just shows the application is started and does not block anything. It likely closes before the user can even close it using the mouse, unless the user already anticipates it to appear. And then the user can already close it right away, also without disturbing any initialization, as that still takes place where it took place before the splash screen was introduced.

And it's really just the major functionality of a splash screen. It's not dumb to put initialization into it and then also protect it from getting closed before that's done, but it's not a must-have and it's not at all the only reason that justifies the splash screen.

You're all just pushing your own idea and oppinion upon David, while what I said in my first reply post in one sentence is enough to fulfill his need.

Chriss
 
Just to relativize my reactions:

I'm not saying you cannot and should not pull initialization into a splash screen. If you do it you can also show progress, as you know the progress stages of your initialization. Still, it's not by any forced circumstance, by design or by technical needs that initialization needs to be moved into a splash screen, and to integrate a splash screen as unplanned add-on after your project already is out of beta phase, you may not like to rearrange things that work as is and just put up a non-modal form and be done with it not being capable to show initialization progress.

Besides that, just when I really limit my answer to what is absolutely the simplest solution to the conccrete question, as i was asked to do, everybody comes up against that. I have rejected this idea of a forum. I actually do support contributing your ideas, and discussing them, by the title of the thread asking for ideas, that's fine in itself and by what i think a forum should be. I just dislike how what I recommmended is completely misunderstood and misinterpreted and discrimintated by you without even verifying your statements. Even those who I know understand what it means a form is non-modal to the execution of the rest of the code and forms. That's not just stating your own version and idea of a splash screen, that's telling my recommendation does not work. That's therefore something I strongly react to, sorry. And I will do it again and again, even if it's Christmas time.

I hope that is clear.

So let me just note that it's surely just 4:1 against me about using the splash screen as dumb splash screen only and the general notion about it is to put initialization into it.


Just notice some facts about what that means: If you connect to MySQL as it's done in this case and also load data into the splash screen dataenvironment, you better make that a default datasession form and also your main form then should continue to use that datasession and not a private one. And that's just one of many possible problems you may cause to David - describing himself as a hobbyist - that he may not see having bad sideeffects of moving the initialization he already has in his Lobbook.scx into the splash screen instead.

I can second one specific idea: To Do the splashscreen Form from the init of the main form is a way to make it appear on top. though better yet the splashscreen form would only be started once the main form is shown already, so the new form appears in front of it, for sure. But that in itsef has one major problem: It delays the display of the splash screeen to after the main forms initialization of the dataenvironment it has is done, thus the splash screen does not appear as immediate as it could. In the interest of this major feature David want - a form that appears as soon as possible - you do the splashscreen form before you do anyhting else. And you can avoid it to appear behind something else by using the alwaysontop property.

It's really all that's necessary, anything else is optional and the dangers you describe only are true when you put initializations into your new splashscreen form and the actual danger is, your main form does either not have its data available or does repeat what the splash screen already did, etc. etc. In the sense of not touching a running system, you better at first introduce a dumb, non-functional splash that only has a visual impact on the start of the application and no other impact.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top