Вы находитесь на странице: 1из 11

Creating a Splash Screen in Delphi

Applications

by Zarko Gajic
Updated May 13, 2018

The most basic splash screen is just an image, or more precisely, a form with an image, that
appears in the center of the screen when the application is loading. Splash screens are
hidden when the application is ready to be used.

Below is more information on the different types of splash screens you may see, and why
they're useful, as well as steps for creating your own Delphi splash screen for your
application.

What Are Splash Screens Used For?


There are several types of splash screens. The most common are start-up splash screens -
the ones you see when an application is loading. These usually display the application's
name, author, version, copyright, an image, or some type of icon, that uniquely identifies it.

If you are a shareware developer, you could use splash screens to remind users to register
the program. These may pop up when the program first launches, to tell the user that they
can register if they want special features or to get email updates for new releases.

Some applications use splash screens to notify the user of the progress of a time-consuming
process. If you look carefully, some really large programs use this type of splash screen
when the program is loading background processes and dependencies. The last thing you
want is for your users to think that your program is "dead" if some database task is
performing.

Creating a Splash Screen


Let's see how to create a simple start-up splash screen in a few steps:

1. Add a new form to your project.


Select New Form from the File menu in the Delphi IDE.
2. Change the Name Property of the Form to something like SplashScreen.
3. Change these Properties: BorderStyle to bsNone, Position to poScreenCenter.
4. Customize your splash screen by adding components like labels, images, panels,
etc.
You could first add one TPanel component (Align: alClient) and play around with
BevelInner, BevelOuter, BevelWidth, BorderStyle, and BorderWidth properties to
produce some eye-candy effects.
5. Select Project from the Options menu and move the Form from the Auto-create
listbox to Available Forms.We'll create a form on the fly and then display it before
the application is actually opened.
6. Select Project Source from the View menu.
You can also do this through Project > View Source.
7. Add the following code after the begin statement of the Project Source code (the
.DPR file):
8.
9. Application.Initialize; //this line exists!
10. SplashScreen := TSplashScreen.Create(nil) ;
11. SplashScreen.Show;
12. SplashScreen.Update;
13. After the final Application.Create() and before the Application.Run statement, add:
14.
15. SplashScreen.Hide;
16. SplashScreen.Free;
17. That's it! Now you can run the application.

In this example, depending on the speed of your computer, you will barely see your new
splash screen, but if you have more than one form in your project, the splash screen will
certainly show up.

For more information on making the splash screen stay a bit longer, read through the code
in this Stack Overflow thread.

Inside project file:

program Project1;

uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
uSplashScreen in 'uSplashScreen.pas' {frmSplashScreen};

{$R *.res}

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;

frmSplashScreen := TfrmSplashScreen.Create(nil);
try
frmSplashScreen.Show;
// Create your application forms here
Application.CreateForm(TForm1, Form1);

while not frmSplashScreen.Completed do


Application.ProcessMessages;
frmSplashScreen.Hide;
finally
frmSplashScreen.Free;
end;

Application.Run;
end.

Inside splash screen unit:

unit uSplashScreen;

interface

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

type
TfrmSplashScreen = class(TForm)
Timer1: TTimer;
procedure FormShow(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
Completed: Boolean;
end;

var
frmSplashScreen: TfrmSplashScreen;

implementation

{$R *.dfm}

procedure TfrmSplashScreen.FormShow(Sender: TObject);


begin
OnShow := nil;
Completed := False;
Timer1.Interval := 3000; // 3s minimum time to show splash screen
Timer1.Enabled := True;
end;

procedure TfrmSplashScreen.Timer1Timer(Sender: TObject);


begin
Timer1.Enabled := False;
Completed := True;
end;

end.

The splash screen will be visible for minimum time of 3 seconds or more if it will take
more time to create all the forms of your application.

Main .dpr file

var SplashScreen : TForm2;

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;

SplashScreen := TForm2.Create(nil); // Creating with nil so this is not


registered as main form
try
SplashScreen.ShowModal; // Blocking the execution for as long as this
form is open
finally
SplashScreen .Free;
end;

Application.CreateForm(TForm1, Form1);
Application.Run;

On the form which will be the 'splash screen' add the timer, enabled at 3000 interval (3s)
with the following event handler

procedure TForm2.Timer1Timer(Sender: TObject);


begin
Self.Close;
end;

Custom Form Shapes with Delphi


Posted on August 27, 2013 by Anthony Dowling

During the early development stages of the Terian ID Software and related products I was
inspired by the “Creating User Experiences: Fundamental Design Principles” Pluralsight
training course by Billy Hollis. I wanted my software to have specific theme or style that
would make each product identifiable to the same family.

The problem being I am not an artistic type of person, and ideas I have in my head for what
I like and want don’t necessarily translate well to an explanation (As anyone that has tried
to do design work for me can attest to). Fortunately one of the demo’s Billy Hollis
demonstrates has a form design which struck a chord with me. Basically the form was
borderless, with the top right corner cut away.

So instead of a form like this…

We end up with one that looks like this…


This design seemed very simple yet elegant to me, so I decided to invest in it across the
entire product range.

Custom Form Shape – Method 1:

Having an idea is one thing, however implementing it is another. Not having any
experience with custom form shapes in Delphi I did a bit of research and one common
method involves utilising a transparent image cut to the appropriate shape. This custom
image is combined with a form that has its Color and TransparentColorValue properties set
to a rarely used colour.

Starting with a blank form perform the following steps…

▪ Set Height/Width
▪ Set BorderStyle = bsNone
▪ Cleared BorderIcons
▪ Set Color = clTeal (Figured this was a Rarely Used Colour)
▪ Set TransparentColorValue = clTeal
▪ Set TransparentColor = True

These are the basic form properties to allow for a transparent form (when used with a
transparent custom shaped image).

The next step is to add the form objects, which results in the following form structure…

The deconstructed form looks like this…


The secret ingredient is the imgCorner image which is a simple triangle with a transparent
background. All other form objects square up nicely and cover the entirety of the form as
the image below demonstrates…

This method works great initially, however it will become cumbersome and time
consuming if you need to add more than half a dozen forms to an application.

Custom Form Shape – Method 1 – Resizing:

Some forms will require resizing functionality, and due to setting the BorderStyle property
to bsNone we can no longer rely on the standard Windows resizing functionality. A
workaround for this is to provide a custom control that mimics a Size Grip in the lower
right corner of the form.

The TSjonesSizeGrip custom control is a simple 10×10 pixel control that descends from
TGraphicControl and contains the Size Grip Image…

TSjonesSizeGrip contains an onMouseDown event which helps mimic form resizing…

procedure TfrmStyleViaMethod1.SjonesSizeGrip1MouseDown(Sender: TObject;


Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
const
sc_DnRightsize = $f008;
begin
// 11/Mar/2013 - ADowling
// ---
// We temporarily set doublebuffering here to help reduce the amount
of flickering that occurs when
// resizing the form.
// ---
self.DoubleBuffered := True;
ReleaseCapture;
Perform(wm_SysCommand, sc_DnRightsize, 0);
self.DoubleBuffered := False;
end;

If all form objects are anchored appropriately then this is all that is required to enable form
resizing. The only downside is that form resizing is only available by dragging the
SizeGrip, where as standard dialogs can be resized using their borders.

Custom Form Shape – Method 2:

Wanting to find an easier and quicker method I did some additional research and came
across a method that utilises the ‘CreatePolygonRgn’ and ‘SetWindowRgn’ Windows API
calls. These calls would allow me to define a polygon region and then assign that as the
visible region of a form.

As the desired custom shape is the same across all forms, the following Procedure is used
to set the custom form shape
Procedure SetTerianFormShape(wnd : HWND; rect : TRect; rgn : HRGN);
Var
arPts : Array[0..4] of TPoint;
Begin
// Point 1
arPts[0].X := 0;
arPts[0].Y := 0;

// Point 2
arPts[1].X := rect.Width - 30;
arPts[1].Y := 0;

// Point 3
arPts[2].X := rect.Width;
arPts[2].Y := 30;

// Point 4
arPts[3].X := rect.Width;
arPts[3].Y := rect.Height;

// Point 5
arPts[4].X := 0;
arPts[4].Y := rect.Height;

rgn := CreatePolygonRgn(arPts, 5, WINDING);


SetWindowRgn(wnd, rgn, TRUE);
End;

The following procedure is used to reset the custom shape.

Procedure UnSetTerianFormShape(wnd : HWND);


Begin
SetWindowRgn(wnd, 0, False);
End;

Each form requires its own Polygon Region handle, so we need to add a private variable to
each form to contain this.

private
{ Private declarations }
TerianFormShapeRGN : HRGN; // Variable to hold Polygon Region Handle

To set the custom shape for each form, the OnCreate Event calls the SetTerianFormShape
Procedure…

procedure TfrmStyleViaMethod2.FormCreate(Sender: TObject);


begin
SetTerianFormShape(self.Handle, self.ClientRect,
self.TerianFormShapeRGN);
end;
This method of creating Custom Shaped Forms in Delphi is far simpler from a development
perspective, as you can easily add new forms with varying sizes with no need to manipulate
multiple shape objects.

The form structure is simplified to this…

The form Color property is set to the desired background colour, and no additional shape
objects are required.

Custom Form Shape – Method 2 – Resizing:

Form resizing is handled in a similar way to method 1. However, due to the Window
Region being set via a static polygon on form creation you need to reset the polygon region
to allow the form to be visible outside the initial bounds of the form (in the event of
increasing the form size). To perform this you simply Unset the Custom Form shape,
perform the resize, and then reset the Form Shape like follows…

procedure TfrmStyleViaMethod2.SjonesSizeGrip1MouseDown(Sender: TObject;


Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
const
sc_DnRightsize = $f008;
begin
CustomResizing := True; // Used to avoid FormResize Event Also
Resetting Custom Form Shape.

UnSetTerianFormShape(self.Handle);

// 11/Mar/2013 - ADowling
// ---
// We temporarily set doublebuffering here to help reduce the amount
of flickering that occurs when
// resizing the form.
// ---
self.DoubleBuffered := True;
ReleaseCapture;
Perform(wm_SysCommand, sc_DnRightsize, 0);
self.DoubleBuffered := False;

SetTerianFormShape(self.Handle, self.ClientRect,
self.TerianFormShapeRGN);

CustomResizing := False;
end;
Note: The additional variable called CustomResizing (defined in forms
implementation) helps ensure the FormResize event does not attempt to reset the custom
form shape when using the SizeGrip.

Similarly to the method 1 if all form objects are anchored appropriately no other processes
are required to handle form resizing.

Custom Form Shape – Method 2 – Resizing Main Form Issue:

If method 2 is used to provide a custom form shape for the main form of an application,
there is a small issue in regards to form resizing. If an applications shortcut is set to run the
application Maximised then the custom form shape is not reset, and part of the form will
not be displayed.

To avoid this issue you need to reset the custom form shape as part of the Form onResize
event…

procedure TfrmMain.FormResize(Sender: TObject);


begin
// 26/Aug/2013 - ADowling
// ---
// We need to reset the TerianFormShape upon resizing, usually we do
this as part of the custom
// resizing performed in the SjonesSizeGrip1MouseDown method,
however it is possible there are
// other calls to FormResize (such as when an application is set to
Run Maximized), in which case
// we need to ensure the TerianFormShape is reset.
// ---

if Not CustomResizing then Begin


UnSetTerianFormShape(self.Handle);
SetTerianFormShape(self.Handle, self.ClientRect,
self.TerianFormShapeRGN);
CheckIfStretchRequired;
end;
end;

So far it works:

So far using method 2 has worked a charm, and from the end user perspective they seem
quite happy. Granted method 1 also worked well, and from the end user perspective they
noticed no difference, however the ease of creating new forms with method 2 is certainly
far superior than messing around with multiple shape objects.

One item still on my to-do list, is testing these methods with font scaling to see how that
might affect the forms and/or resizing.

Вам также может понравиться