Для запуска приложения порой достаточно одного клика. Но иногда время запуска оказывается больше ожидаемых одной-двух секунд, и тогда у пользователя может возникнуть ощущение, что программа зависла и что-то пошло не так. Избежать этого можно, если сократить время до появления первого окна, которое называют заставкой (англ. splash screen).
Для этого все действия по подготовке программы к работе выполняются после отображения заставки. А сама заставка становится границей, отделяющей серые будни пользователя Windows от фантастического мира вашего приложения.
Визуальная часть
Заставка – это визитная карточка приложения. Единых правил по её оформлению нет и быть не может. И если при проектировании дизайна основного приложения необходимо придерживаться определенных правил и соглашений, то при отображении заставки можно себя не сдерживать и позволить себе проявление своих творческих дарований в полной мере: используйте яркие палитры или черно-белые скетчи, добавьте анимацию или сделайте заставку полупрозрачной, откажитесь от прямоугольной формы. Но, если вы привыкли к сдержанности и экономному использованию ресурсов, я могу предложить решение, которое для своей реализации использует скрипты и файл изображения.

В качестве фонового изображения используется картинка, которая находится в папке Images\Logo, поверх фона отображается название приложения. Название имеет черную тень, которая улучшает читабельность текста. В нижнем левом углу выводится номер версии программы. Так как время инициализации приложения зависит от производительности компьютера, то желательно отображать заставку в течение указанного в настройке времени, но не более чем.
Скрипты
Для создания формы-заставки используется функция Splash_Create(). Она возвращает созданную форму в качестве результата. Параметры создания вынесены в константы.
const
SPLASH_LOGO_WIDTH = 350; // Ширина изображения
SPLASH_LOGO_HEIGHT = 169; // Высота изображения
SPLASH_BORDER = 2; // толщина рамки вокруг изображения
SPLASH_BORDER_COLOR = clBlack; // цвет рамки
SPLASH_FILE_NAME = 'Images\Logo\logo_350x169.jpg'; // файл фонового изображения
SPLASH_FONT_SIZE = 28; // размер шрифта для названия
SPLASH_FONT_COLOR = clWhite; // цвет для названия
SPLASH_SHADOW_COLOR = clBlack; // цвет тени
SPLASH_VER_FONT_SIZE = 11; // размер шрифта для версии
SPLASH_VER_FONT_COLOR = clWhite; // цвет шрифта для версии
function Splash_Create:TForm;
var
tmpImage:TImage;
tmpLabel:TLabel;
tmpImageFileName:string;
begin
Result := TForm.Create(Application);
with Result do
begin
Width := SPLASH_LOGO_WIDTH + SPLASH_BORDER*2;
Height := SPLASH_LOGO_HEIGHT + SPLASH_BORDER*2;
BorderStyle := bsNone;
Position := poScreenCenter;
Color := SPLASH_BORDER_COLOR;
StyleElements := 0;
end;
// добавить картинку
tmpImage := TImage.Create(Result);
with tmpImage do
begin
Parent := Result;
Width := SPLASH_LOGO_WIDTH;
Height := SPLASH_LOGO_HEIGHT;
Top := SPLASH_BORDER;
Left := SPLASH_BORDER;
tmpImageFileName := ExtractFilePath(Application.ExeName)+SPLASH_FILE_NAME;
if not FileExists(tmpImageFileName) then
RaiseException('Splash_Create() Не найден файл '+tmpImageFileName)
else
Picture.LoadFromFile(tmpImageFileName);
end;
// добавить название
tmpLabel := TLabel.Create(Result);
with tmpLabel do
begin
Name := 'AppName';
Parent := Result;
Top := 0;
Left := 0;
Autosize := False;
Width := Result.ClientWidth;
Height := Result.ClientHeight;
Alignment := taCenter;
Layout := tlCenter;
WordWrap := True;
StyleElements := 0;
Caption := APP_NAME;
Font.Size := SPLASH_FONT_SIZE;
Font.Color := SPLASH_FONT_COLOR
end;
Label_AddShadow( tmpLabel, SPLASH_SHADOW_COLOR ); // добавить тень
// добавить номер версии
tmpLabel := TLabel.Create(Result);
with tmpLabel do
begin
Name := 'AppVer';
Parent := Result;
Caption := APP_VERSION;
StyleElements := 0;
Font.Size := SPLASH_VER_FONT_SIZE;
Font.Color := SPLASH_VER_FONT_COLOR;
Left := Height div 2;
Top := Result.ClientHeight - Height - (Height div 2);
end;
Label_AddShadow( tmpLabel, SPLASH_SHADOW_COLOR, 1 ); // добавить тень
end;
Code language: Delphi (delphi)
Давайте посмотрим на него внимательно. В шестьдесят третьей строке вызывается процедура Label_AddShadow(), которая добавляет тень для указанного текста.
Тень – это точная копия компонента-метки, обычно имеющая черный цвет текста (любо заданный цвет, темнее основного). Она располагается с небольшим смещением позади заданной метки. По непонятным причинам в MVDB метод Assign() для компонента TLabel не поддерживается, поэтому для получения копии пришлось писать кучу кода:
procedure Label_AddShadow( ALabel:TdbLabel; AColor:TColor = 0; );
var
tmpLabel:TdbLabel;
begin
tmpLabel := TdbLabel.Create( ALabel.Owner );
// tmpLabel.Assign( ALabel ); // К сожалению, в MVDB данный метод не работает :(, поэтому прийдется скопировать все свойства вручную....
// все, что ниже, можно заменить одной командой Assign, но в MVD она не работает...
tmpLabel.Parent := ALabel.Parent;
tmpLabel.Name := ALabel.Name + SX_SHADOW;
tmpLabel.Caption := ALabel.Caption;
tmpLabel.AutoSize := ALabel.AutoSize;
tmpLabel.Width := ALabel.Width;
tmpLabel.Height := ALabel.Height;
tmpLabel.Anchors := ALabel.Anchors;
tmpLabel.Font := ALabel.Font;
tmpLabel.StyleElements := ALabel.StyleElements;
tmpLabel.Alignment := ALabel.Alignment;
tmpLabel.Layout := ALabel.Layout;
tmpLabel.WordWrap := ALabel.WordWrap;
// задать смещение тени
tmpLabel.Top := ALabel.Top + LABEL_SHADOW_SHIFT;
tmpLabel.Left := ALabel.Left + LABEL_SHADOW_SHIFT;
// задать цвет тени
tmpLabel.Font.Color := AColor;
ALabel.BringToFront; // поместить главную надпись перед тенью
end;
Code language: Delphi (delphi)
Инициализация и запуск
Перед тем, как главная форма приложения frmMain (её название на закладке визуального конструктора отмечается красным цветом) отобразится, происходит событие OnShow, которое мы будем использовать для создания и отображения заставки, а также выполнения действий по инициализации приложения.
procedure frmMain_OnShow (Sender: TObject; Action: string);
// отображение главной формы
begin
// отобразить в заголовке главной формы название и версию программы
frmMain.Caption := APP_NAME + ' '+APP_VERSION;
App_Splash_Start;
frmMain.pgcMain.ActivePage := frmMain.tshNavigation; // открыть вкладку "Навигация"
frmMain.pgcNavigation.ActivePage := frmMain.tshTask; // открыть вкладку "Задачи"
end;
Code language: Delphi (delphi)
Для инициализации приложения с отображением заставки вызывается процедура App_Splash_Start(), в которой создается и отображается форма – заставка, а затем вызывается процедура инициализации приложения App_Start(). После её завершения производится замер затраченного на инициализацию время и, если оно не превышает заданного, то добавляется задержка ровно на столько, чтобы суммарное время отображения заставки соответствовало заданному в константе APP_SPLASH_DELAY_MIN. После чего заставка уничтожается, затем отображается основная форма frmMain.
procedure App_Splash_Start;
// инициализация с заставкой
var
tmpForm:TForm;
tmpStartTime: TTime;
tmpSleepTime: integer;
begin
tmpForm := Splash_Create;
tmpForm.Show;
Application.ProcessMessages;
tmpStartTime := Time();
App_Start;
// гарантированная задержка, но не более указанной в APP_SPLASH_DELAY
tmpSleepTime := APP_SPLASH_DELAY_MIN - Trunc( (Time() - tmpStartTime)*24*60*60*1000 );
if tmpSleepTime > 0 then
Sleep(tmpSleepTime);
tmpForm.Close;
tmpForm.Free;
end;
Code language: Delphi (delphi)
В App_Start() происходит инициализация подсистем приложения: управление картинками кнопок, стилями, горячими клавишами и т.д..
procedure App_Start;
// запуск приложения
begin
// тут должна быть всяческая инициализация, которая может занять продолжительное время
App_InitSystemVar; // инициализация системных переменных
Images_Init; // инициализация подcистемы загрузки картинок
Style_Init; // активация стиля
Style_CreateMenu(frmMain); // добавить стили в меню
UserApp_InitForm; // создать формы
UserApp_InitVar; // настроить переменные
// инициализация, которая идет после настройки переменных
CE_Init(MainForm); // главное меню находится на главной форме, но отображается там, где нужно
Hotkey_Init(MainForm); // подключить горячие клавиши
UserApp_InitBase; // инициализация базы данных
end;
Code language: Delphi (delphi)
Таким образом, в базовом комплекте будут две процедуры инициализации: с отображением заставки и без её отображения. Это позволит гибко подходить к выбору оптимального решения. Для лёгких приложений можно вызывать App_Start(), а если инициализация долгая, то лучше использовать App_Splash_Start();
Если вы хотите использовать статическую заставку, созданную в визуальном конструкторе My Visual Database, то откорректируйте App_Splash_Start(), вызывая в ней вашу статическую форму frmSplash:
procedure App_Splash_Start;
// инициализация с заставкой
var
tmpStartTime: TTime;
tmpSleepTime: integer;
begin
frmSplash.Show;
Application.ProcessMessages;
tmpStartTime := Time();
App_Start;
// гарантированная задержка, но не более указанной в APP_SPLASH_DELAY
tmpSleepTime := APP_SPLASH_DELAY_MIN - Trunc( (Time() - tmpStartTime)*24*60*60*1000 );
if tmpSleepTime > 0 then
Sleep(tmpSleepTime);
frmSplash.Hide;
end;
Code language: Delphi (delphi)
Дополнительные улучшения
Заодно можно улучшить внешний вид формы “О программе”, заменив стандартную картинку на свою собственную. Для этого в процедуру App_InitAboutForm() добавим несколько строчек:
FindC(frmdbCoreAbout,'Image1',tmpImage);
tmpImageFileName := ExtractFilePath(Application.ExeName)+ABOUT_LOGO_FILE_NAME;
if not FileExists(tmpImageFileName) then
RaiseException('Splash_Create() Не найден файл '+tmpImageFileName)
else
tmpImage.Picture.LoadFromFile(tmpImageFileName)
Code language: Delphi (delphi)
