Программирование на Lazarus

Экранная заставка

Показывать лекцию целиком

Цель лекции

Закрепление пройденного материала на практике, изучение компонента TTimer и функции-генератора случайных чисел Random().

Постановка задачи

Время от времени для закрепления пройденного материала мы будем выполнять лабораторные работы - реальные программные проекты различной сложности. На этот раз мы с вами сделаем экранную заставку в виде электронных часов. Проект разрабатывается на платформе Windows XP SP3, но и на других версиях Windows должно получиться также.

Прежде всего, экранная заставка занимает весь экран, не имеет системной строки, главного меню и обрамления главного окна. Да и окно у экранной заставки, как правило, одно. Еще одно различие - файл с экранной заставкой имеет расширение *.scr (от англ. screen - экран) а не *.exe, как программа. Тем не менее, экранная заставка - та же программа.

Подумаем, каким образом мы можем реализовать такую заставку в виде часов. Ответ напрашивается сам собой: установить в центре экрана обычную панель, на которой в свойстве Caption выводить текущее время. Однако, это скучно. Пусть эта панель еще и перемещается по экрану по случайной траектории! Чтобы реализовать такой проект, нам придется изучить пару вещей: системный таймер TTimer и функцию-генератор случайных чисел Random().

Реализация проекта

Вообще-то, вначале положено разработать алгоритм программы.

Алгоритм - набор инструкций, описывающих порядок действий исполнителя для достижения результата решения задачи за конечное число действий (из Википедии).

Но наш проект достаточно прост, поэтому алгоритма, как такового, нет. Начнем проект, при необходимости разрабатывая алгоритм дальнейших действий по ходу дела. Откройте Lazarus с новым проектом, свойство Name главной формы сразу переименуйте в fMain. Сохраните проект в папку 11-01 под именем MyClock, а модуль главной формы назовите Main.

Теперь займемся окном. Поскольку у окна заставки не должно быть системной строки, свойство BorderStyle установим в bsNone. А так как это окно должно занимать весь экран, свойство WindowState переведем в wsMaximized. Свойство Color установим в clBlack, чтобы форма стала черной. И ещё: свойство формы Cursor переведем в crNone, чтобы в работающей заставке не было видно указателя мыши (зачем она там?).

Пойдем далее. Установим на форму метку TLabel. Не обращайте внимания, что на черном фоне её пока не видно на форме. Изменим у неё некоторые свойства:

  • Name = lClock (так мы будем обращаться к метке в программном коде; l - сокращение от label - метка, Clock - часы)
  • Caption = 00:00:00
  • Font = Times New Roman, жирный курсив, 48 пикселей. Цвет шрифта выберите желтый.
  • ParentColor = True (это заставит метку всегда сливаться с формой, а цвет шрифта будет контрастировать с общим фоном)
  • Если вы забыли, как настроить свойства шрифта, то напомню: нужно выделить свойство Font, затем нажать на кнопку с тремя точками в правой части свойства, в Инспекторе объектов:

    (рис 11.1) Установка свойств шрифта

    Откроется окно, где вы сможете выбрать шрифт, начертание, размер и цвет шрифта. Можете выбрать свои цвета для шрифта и панели, главное, чтобы они контрастировали друг с другом, и хорошо сочетались с черным цветом формы, который мы установим позже.

    В результате выполненных действий у вас должно получиться примерно такое окно:

    (рис 11.2) Окно главной формы

    Не волнуйтесь по поводу того, что окно пока маленькое, а системная строка и обрамления окна есть - когда программа будет работать, окно займет весь экран, если вы не напутали с параметрами формы.

    Компонент TTimer

    Пришла очередь таймера. Он нам нужен, чтобы заставить надпись метки меняться - показывать текущее время. Кроме того, благодаря этому компоненту мы сможем обеспечить метке непрерывное движение.

    Таймер TTimer находится на вкладке System Палитры компонентов:

    (рис 11.3) Компонент TTimer

    Компонент этот невизуальный - невидимый для пользователя, поэтому его можно установить в любое место на форме, лишь бы он вам не мешал при проектировании формы, не перекрывал другие компоненты. Компонент будет вам виден, несмотря на черный цвет формы.

    У компонента есть всего по одному свойству и событию, которые нам могут понадобиться:

    Interval - это свойство устанавливает интервал времени, когда таймер сработает. По умолчанию, он равен 1000, что соответствует 1 секунде. Это нам и нужно, поэтому оставим значение свойства без изменений. А на будущее запомните: если вам потребуется установить другое время, то умножайте требуемое количество секунд на 1000, и получите то, что нужно.

    Далее, переходим в Инспекторе объектов на вкладку События. Нас интересует только одно событие:

    OnTimer - событие срабатывает всякий раз, когда заканчивается установленный интервал. Сгенерируйте код для этого события так же, как ранее генерировали событие OnClick для кнопок, мы заполним его чуть позже.

    Вот теперь нам требуется продумать алгоритм действий - как мы будем двигать надпись. Идея такова: сгенерируем случайное число от 0 до 3, получится 4 варианта. Ведь у нас есть 4 направления, куда двигаться: вверх, вниз, влево или вправо. В зависимости от полученного случайного числа будем выбирать и направление движения. Двигать будем, скажем, на 50 пикселей влево-вправо, или на 25 пикселей вверх-вниз. А как двигать? Да очень просто! Left - это расстояние в пикселях от левого края формы до компонента. Допустим, у метки Left равен 100. То есть, от края формы до метки 100 пикселей. Если мы прибавим еще 50, то тем самым, сдвинем метку вправо, а если наоборот, отнимем, то сдвинем влево. Для движения вверх-вниз используем свойство Top - расстояние от верхней части формы до компонента. Движения будут аналогичные, но на 25 пикселей.

    Если получим направление 0, то двигать будем вправо: прибавлять к свойству Left метки 50 пикселей. Если направление 1, то двигаем влево, отнимая 50 пикселей от свойства Left. Если направление 2, то двигаем вниз: прибавляем 25 пикселей к свойству Top метки. Ну и если направление 3, то двигаем вверх, прибавляя 25 пикселей к свойству Top.

    Причем может случиться и так, что надпись окажется за пределами окна. В этом случае нам нужно будет вернуть её обратно в эти пределы. Сделаем это следующим образом: если метка ушла влево, то свойству Left просто присвоим значение 0 - метка вернется в пределы формы и окажется прижатой к левому краю.

    Если метка ушла за правый край, то присвоим свойству Left ширину формы минус ширину метки, таким образом, метка окажется прижатой к правой части формы и будет в её пределах.

    Точно таким же образом будем возвращать метку, если она уйдет вверх или вниз за пределы формы.

    Значит, нам потребуется только одна целочисленная переменная, в которую мы будем генерировать направление - 4 позиции. Для этого используем функцию Random(), которую ещё называют генератором случайных чисел.

    Random() - функция возвращает случайное число (англ. random - случайный) от 0 до указанного количество чисел минус один. Синтаксис очень простой:

    Random(<количество чисел>);
        

    Функция вернет случайное число от 0 до <количество чисел> - 1. То есть, в случае

    i:= Random(4);
        

    в переменную i попадет случайное число от 0 до 3. Этим мы и воспользуемся. А чтобы не тратить лишнюю память, переменную i объявим с типом byte.

    Несмотря на амбициозную идею, код события OnTimer будет довольно прост:

    procedure TfMain.Timer1Timer(Sender: TObject);
    var
      i: byte; //для получения случайного числа
    begin
      //первым делом меняем надпись метки:
      lClock.Caption:= TimeToStr(Now);
      //получаем случайное направление:
      i:= Random(4);
      //теперь в зависимости от направления двигаем метку:
      case i of
        0: lClock.Left:= lClock.Left + 50; //вправо
        1: lClock.Left:= lClock.Left - 50; //влево
        2: lClock.Top:= lClock.Top + 50; //вверх
        3: lClock.Top:= lClock.Top - 50; //вниз
      end;
      //теперь проверяем: не вышла ли метка за пределы формы?
      //если вышла - возвращаем её обратно
      //если ушла влево:
      if lClock.Left < 0 then lClock.Left:= 0;
      //если ушла вверх:
      if lClock.Top < 0 then lClock.Top:= 0;
      //если ушла вправо:
      if (lClock.Left + lClock.Width) > fMain.Width then
        lClock.Left:= fMain.Width - lClock.Width;
      //если ушла вниз:
      if (lClock.Top + lClock.Height) > fMain.Height then
        lClock.Top:= fMain.Height - lClock.Height;
    end;
        

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

    lClock.Caption:= TimeToStr(Now);
        

    Таким образом, мы присваиваем свойству Caption метки lClock текущее время. Работе с датой и временем у нас будет посвящена следующая лекция, так что пока на этом не зацикливайтесь. Весь остальной код должен вам быть понятен.

    Собственно, проверить работу заставки можно уже сейчас, только не забудьте предварительно сохранить изменения. Чтобы закрыть окно, у которого нет для этого кнопок и меню, воспользуйтесь стандартными кнопками Windows <Alt + F4>.

    Но заставка на этом еще не закончена. Прежде всего, из-за включенной отладочной информации программа имеет большой размер, почти 15 мегабайт! Кроме того, мы получили исполняемый exe-файл, а нам нужна заставка с расширением *.scr. Исправляем эти недостатки:

  • Выбираем команду меню <Проект -> Параметры проекта>.
  • В разделе <Параметры компилятора> выбираем подраздел <Пути>.
  • В поле <Имя исполнимого файла (-о)> вместо MyClock указываем MyClock.scr (то есть, добавляем нужное расширение).
  • Отключаем флажок <Применять соглашения по именованию>, чтобы не было конфликта расширений.
  • В разделе <Параметры компилятора> переходим на подраздел <Компоновка>.
  • Отключаем флажок <Генерировать отладочную информацию для GDB>, чтобы уменьшить размер полученного файла.
  • Сохраняем проект, и заново его запускаем. В результате в папке 11-01 получаем требуемый файл MyClock.scr размером чуть больше 1,5 мегабайта.
  • Если вас устраивает, что для закрытия заставки приходится нажимать <Alt + F4>, то ничего больше делать не нужно. Но мне бы хотелось, чтобы эту заставку можно было закрыть кнопкой <Esc> (код которой 27 в таблице символов ANSI), как любую другую нормальную заставку. А для этого придется самую малость доработать проект.

    Вернитесь в Редактор форм, и выделите саму форму. В Инспекторе объектов перейдите на закладку События и сгенерируйте событие формы OnKeyPress, которое срабатывает при нажатии на любую кнопку:

    (рис 11.4) Событие формы OnKeyPress

    Его код совсем прост:

    procedure TfMain.FormKeyPress(Sender: TObject; var Key: char);
    begin
      //если нажали Esc, то выходим:
      if Key = #27 then Close;
    end;
        

    Сохраните проект и снова его запустите. Заставка теперь должна закрываться при нажатии клавиши <Esc>. Lazarus нам больше не нужен, можете его закрыть.

    Установка заставки в Windows

    Большинство из вас наверняка знает, как полученную заставку установить в своей Windows. Для тех, кто этого все-таки не знает, расскажу подробно:

  • Найдите файл MyClock.scr, он должен быть в папке 11-01, где вы храните проекты.
  • Скопируйте этот файл в папку C:\Windows
  • Щелкните правой кнопкой по свободному от окон месту Рабочего стола и выберите команду "Свойства".
  • В открывшемся окне "Свойства: Экран" перейдите на вкладку "Заставка".
  • Там выберите нашу заставку и требуемый интервал её появления, после чего нажмите <OK>:
  • (рис 11.5) Выбор заставки и интервала

    Если пользователь в течение указанного интервала не будет двигать мышью и не нажмет никакой клавиши, то появится наша заставка. На сегодня это всё.

    Вернуться к учебному плану