2008. január 5., szombat
Display different splash screens anytime during program execution
Problem/Question/Abstract:
How to display different splash screens anytime during program execution
Answer:
Solve 1:
I wanted to be able to display a splash screen anytime during the program run with different durations and different images each time. The problem with using the Release method from within a form is that it doesn't set the variable referencing the splash form to NIL. When the splash form is released, I need to reset the reference so that I can test it when displaying the form to make sure it's NIL (that there isn't one already up). I could easily have made the reference public and set it to NIL after calling Release from within the timer event, but that's not very reusable.
What I ended up doing is creating a class (TFormWithSplash) derived from TForm that has all mechanisms necessary to handle the splash screen itself. Then, any form I want to be able to display splashscreens, I simply derive from this class instead of TForm. The unit that defines TFormWithSplash has a simple form within it that contains an image and timer control. The ShowSplash method of TFormWithSplash creates an instance of this form and displays it. This form then loads the image file and starts the timer. When the timer elapses, the form closes itself and sends a user defined message its parent form which frees the reference and resets it to nil. Everything but the PicFileName, SplashDuration, StayOnTop properties and the ShowSplash function calls are invisible to the programmer. Here is the code; it still needs a few features, but seems to work well.
unit SplashFrm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;
const
WM_SPLASHCLOSED = WM_USER + 113;
type
TFormWithSplash = class;
TSplashForm = class(TForm)
Image1: TImage;
Timer1: TTimer;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
procedure FormDeactivate(Sender: TObject);
private
CloseOnDeactivate: Boolean;
procedure LoadAndDisplay(PicFile: string);
public
constructor Create(Owner: TFormWithSplash; DisplayFor: Cardinal;
CloseOnLostFocus: Boolean; TopMost: Boolean);
end;
TFormWithSplash = class(TForm)
PicFile: string;
SplashForm: TSplashForm;
procedure SetPicFile(FileName: string);
procedure OnSplashClosed(var msg: TMessage); message WM_SPLASHCLOSED;
public
SplashDuration: Cardinal;
StayOnTop, CloseOnLostFocus: Boolean;
constructor Create(Owner: TComponent); override;
procedure ShowSplash;
property SplashPicFile: string read PicFile write SetPicFile;
end;
implementation
{$R *.DFM}
constructor TFormWithSplash.Create(Owner: TComponent);
begin
SplashForm := nil;
PicFile := '';
StayOnTop := True;
CloseOnLostFocus := False;
inherited Create(Owner);
end;
procedure TFormWithSplash.OnSplashClosed(var msg: TMessage);
begin
SplashForm.Free;
SplashForm := nil;
end;
procedure TFormWithSplash.SetPicFile(FileName: string);
begin
if not FileExists(FileName) then
raise EInOutError.Create('Couldn''t load image file: ' + FileName)
else
PicFile := FileName;
end;
procedure TFormWithSplash.ShowSplash;
begin
if PicFile = '' then
Exit;
while Assigned(SplashForm) do
Application.ProcessMessages;
SplashForm := TSplashForm.Create(self, SplashDuration, CloseOnLostFocus, StayOnTop);
SplashForm.LoadAndDisplay(PicFile);
end;
constructor TSplashForm.Create(Owner: TFormWithSplash; DisplayFor: Cardinal;
CloseOnLostFocus: Boolean; TopMost: Boolean);
begin
inherited Create(Owner);
CloseOnDeactivate := CloseOnLostFocus;
if TopMost then
FormStyle := fsStayOnTop;
Image1.AutoSize := True;
Timer1.Interval := DisplayFor * 1000;
end;
procedure TSplashForm.LoadAndDisplay(PicFile: string);
begin
Image1.Picture.LoadFromFile(PicFile);
ClientHeight := Image1.Picture.Height + 1;
ClientWidth := Image1.Picture.Width + 1;
Left := Screen.Width div 2 - Width div 2;
Top := Screen.Height div 2 - Height div 2;
Show;
end;
procedure TSplashForm.FormShow(Sender: TObject);
begin
Application.RestoreTopmosts;
Timer1.Enabled := True;
end;
procedure TSplashForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
PostMessage(TFormWithSplash(Owner).Handle, WM_SPLASHCLOSED, 0, 0);
end;
procedure TSplashForm.Timer1Timer(Sender: TObject);
begin
Close;
end;
procedure TSplashForm.FormDeactivate(Sender: TObject);
begin
if CloseOnDeactivate then
begin
Timer1.Enabled := False;
Close;
end;
end;
end.
Solve 2:
This information is found in the View Menu and then view Project Source.
begin
SplashScreen := TSplashScreen.Create(Application); //These 3 lines
SplashScreen.Show; //Added Manually
SplashScreen.Update; //to load SplashScreen
Application.Initialize;
Application.Title := 'Application Title';
Application.CreateForm(TForm1, Form1);
SplashScreen.Hide; //These 2 added
SplashScreen.Free; //manually to close Splash
Application.Run;
end.
In Project Options, set SplashScreen Form to be an available form, not Autocreate.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése