Создаем Screen Saver!
4 февраля 2004
Рубрика: Технологии.
Автор: .
pic

Урок 3

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

Для начала давайте подумаем: а что же вообще такое — хранитель экрана? Наверняка вам сразу представился темный экран с какими-то узорами или картинками, но в первую очередь Screen Saver — это исполнимая программа. Не надо удивляться, но, грубо говоря, хранитель экрана — это то же самое, что и любая другая программа (Word, IE, Paint, PhotoShop…) на вашем компьютере, только с расширением *.SCR.

— То есть скринсейвером может стать и калькулятор? — спросите вы. Ну, в принципе, да. Если поменять название калькулятора, например на «calc.scr», а затем, щелкнув по нему правой кнопкой мыши, выбрать пункт «установить», то калькулятор будет появляться каждый раз в качестве хранителя экрана во время длительного простоя вашего компьютера.

У вас может возникнуть и другой вопрос:
— А зачем вообще писать скринсейвер, если их и так полным-полно. По той же причине, что и пишут другие программы. К примеру, у меня на компьютере вместо стандартных Блокнота и WordPad’а стоят мои собственные программы. Блокнот я заменил, когда мне в компьютер попал троян и записал себя вместо него. Тогда мне не хотелось переустанавливать Windows, и я просто написал новый Блокнот. Кстати, добавил горячие клавиши к командам типа «Сохранить» и «Открыть», а раньше этого не было, и еще он стал открывать файлы более 64 килобайт, в то время как стандартный Блокнот Windows большие файлы открывает в WordPad’е. WordPad же я поменял на свой просто так — большие файлы он открывал по 10-20 секунд (я имею в виду файлы по нескольку сотен килобайт).

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

Есть в этом деле и пара нюансов. К примеру, когда вы щелкаете правой кнопкой мыши по файлу *.SCR, кроме пункта «Установить», есть еще и «Настройка». Обычно при выборе этого элемента контекстного меню выводится формочка с настройками скринсейвера.
Если хотите, вы тоже можете сделать это следующим образом. Если хранитель экрана запускается просто так (двойным щелчком или во время простоя), то вашему приложению передается параметр командной строки: «/S». Если же вашу программу хотят настроить, то никаких параметров скринсейверу не передается.

pic

Параметры командной строки в программе, созданной в Visual Basic, как вы знаете, хранятся в переменной Command. Поэтому, чтобы сделать настраиваемый хранитель экрана, надо ввести следующий код в событие Load главной формы (или в Sub Main):

Private Sub Form_Load()
If Command <> «/S» Then НУЖНОЕ ДЕЙСТВИЕ: Unload Me
End Sub

Вместо НУЖНОЕ ДЕЙСТВИЕ вы можете ввести, например, «frmOptions.Show». Тогда появится форма frmOptions, но естественно, эту форму сначала нужно создать. А можно поместить просто MsgBox — «Нет настроек» или MsgBox «Copyright (C) 2003 by Daniyar Atadjanov». В таком случае при вызове настроек будет выскакивать какое-то сообщение.

Я предлагаю создать простой, ничем не примечательный, хранитель экрана. При желании вы можете его подправить или полностью изменить. Мой вариант — это просто темный экран, на котором будут появляться крупные (или мелкие) точки разных цветов.

Сначала главные определения (в VB они называются General Declarations):

Option Explicit
Dim n, XX, YY, XXX, YYY As Integer
Dim NewLoad As Boolean

Как видите, мы не будем использовать никаких API-функций. Для начинающих поясню, для чего нужно «Option Explicit». Это надо для того, чтобы VB, так сказать, «требовал» определения всех переменных в программе, иначе могут возникнуть ошибки. Многие начинающие боятся это писать, так как не понимают, что им хочет сказать VB словами «Variable Not Defined». Не нужно пугаться. Ничего страшного не произошло, просто значит, вы не объявили переменную, на которую показывает вам Visual Basic. Если вы будете пользоваться этой переменной во всей программе (к примеру, каким-то числом будут пользоваться все функции и процедуры), то надо их объявлять в самом верху (глобальные объявления). Если же переменная нужна только внутри функции (локальная), а после ее использования нам ее значение не понадобится, то объявлять ее следует внутри функции или процедуры (так, например, далее мы объявим переменную «i» в процедуре таймера).

Во всех других языках программирования (С++, Delphi, Паскаль и др.), в отличие от VB, объявление переменных обязательно, и если вы этого не сделаете, то компилятор будет сообщать вам об ошибке.
Вы еще не запутались в функциях-процедурах? Опять же немного поясню: функция и процедура — это разные, но очень похожие вещи. Процедура — это часть программы, которая обрабатывается в определенный момент (в программе все состоит из процедур и функций). Почти у всех компонентов (особенно видимых) бывает несколько процедур. Процедура может вызываться из любой точки программы (не все, правда), и ей могут передаваться какие-нибудь параметры (на языке программирования — аргументы), а она никаких аргументов возвращать не может. Отличие функции от процедуры в том, что она может не только получать аргументы, но и возвращать их.
Чтобы вы поняли суть, рассмотрим следующее.
Вот процедура:

Private Sub SubName (A As String, B As String)
‘Как видите, процедура может принять два текстовых аргумента — A и B
‘А здесь будут описаны действия, которые выполняет процедура:
MsgBox A & vbCrLf & B
End Sub

Вы можете в любой части программы написать SubName («Привет!», «Как дела?»), и программа перейдет к обработке процедуры (она покажет сообщение «Привет! Как дела?»), а после завершения ее работы программа продолжит свою работу дальше.

Еще одна функция:

Private Function FuncName (A As Integer, B As Integer)
‘Функция получит два аргумента в виде чисел (Integer)
‘Прибавляем полученные аргументы и возвращаем значение:
FuncName = A + B
End Function

Если теперь в коде программы написать MsgBox FuncName (20, 5), то наша функция получит аргументы A и B со значениями 20 и 5 соответственно. Функция возвратит прибавленные переменные и FuncName будет равно 25. Следовательно, появится окно сообщения «25».
В других языках программирования, в отличие от VB, возвращение значения происходит не приравниванием этого самого значения его названию, а оператором return (например, в JavaScript, CGI, Perl, PHP, C, C++, Java и еще много-много других).

Есть еще один важный аспект (это относится ко всем языкам) — возвращать значение можно ТОЛЬКО ОДИН РАЗ! Возвращение значения означает конец функции. Если вы напишете:

FuncName = A+B
FuncName = (A+B+A+B) * 100+A+B,

то функция возвратит значение 25 (в нашем случае) и закончится. Это все равно, что писать какой-либо код после оператора End.
Ну, вроде немного объяснил. Теперь вернемся к созданию хранителя экрана.

Далее, думаю, надо сообщить вам об изменении свойств формы и других объектов (надеюсь, вы уже создали проект Standard.EXE с формой).

Изменим свойства формы (это делается на панели «Properties»):

Caption = «My Screen Saver» (можете задать любое).
Name = frmMain (любое)
BackColor = &H00000000& (это код черного цвета)
BorderStyle = 0-None (чтобы не было рамок и кнопок управления формой)
WindowState = 2-Maximized (теперь форма будет появляться в развернутом виде)
ScaleMode = 3-Pixel (именно пиксели, а то майкрософтовцы придумали дурацкий Twip, да еще и установили его по умолчанию).

Кажется, все. Да и еще! Найдите на винчестере или сделайте сами пустой файл CUR (курсор Windows), который ничего не содержит (я имею в виду: ничего не рисуя, сохранить, а не просто создать пустой файл). Нажмите на кнопочку справа у свойства MouseIcon нашей формы. Но это не все. Еще измените свойство MousePointer на 99-Custom.

Вот теперь при появлении нашей формы (можете просмотреть результат, нажав F5) вы не увидите курсора мышки, хоть он и существует.

Продолжим оформление формы и добавление нужных компонентов: добавим таймер (Timer на панели Components) на форму. За его оформление и расположение можете не волноваться, так как компонент невидим, а вот о главном свойстве таймера Interval надо позаботиться. Задайте этому свойству значение 500 (это пока, а потом, поэкспериментировав, вы зададите то, что вам понравится).

Также надо нарисовать на форме надпись — Label. Задаем ему следующие свойства (вернее, изменяем их):

Name = Label (именно Label!)
Caption = «http://visualbasic.boom.ru» (вот здесь и можете написать все, что угодно. Я сделал что-то типа рекламы на свой сайт, а вы можете написать имя автора).
AutoSize = True
BackColor = &H00000000& (код черного цвета)
ForeColor = &H00FFFFFF& (а это белый, хотя он будет меняться во время работы программы, так что можете и не задавать).

Затем нажмите на кнопочку слева от свойства Font и выберите нужный шрифт, и главное — крупный (у меня 24), так как по умолчанию стоит 8, а такой в скринсейвере даже муравей не разглядит.

А теперь рисуем на форме самое главное — элемент Line. У него обязательно изменяем следующие свойства:

Name = L (именно L!)
BorderStyle = 0-Solid
BorderWidth = 10 (толщина линии в пикселях)
Index = 0 (это надо ОБЯЗАТЕЛЬНО, так как далее мы будем «размножать» наши линии на форме)
Ладно, цвет тоже изменим — BorderColor = &H00FFFFFF& (белый, чтобы на черной форме был виден).

Затем вписываем следующий код в процедуру Load:

Private Sub Form_Load()
n = 0
NewLoad = True
End Sub

Дважды щелкаем на таймере (или нажимаем F7), и у нас снова откроется код программы с единственной процедурой таймера, которая так и называется — Timer.

Вписываем в него следующий код:

Private Sub Timer1_Timer()
Randomize Timer
Dim i As Integer
i = 0
1:
i = i + 1
n = n + 1
Load L(n)
L(n).X1 = (Me.ScaleWidth * Rnd)
L(n).Y1 = (Me.ScaleHeight * Rnd)
L(n).X2 = L(n).X1
L(n).Y2 = L(n).Y1
L(n).BorderColor = RGB((224 * Rnd), (224 * Rnd), (224 * Rnd))
L(n).Visible = True
If i < 10 Then GoTo 1 Label.ForeColor = RGB((224 * Rnd), (224 * Rnd), (224 * Rnd)) End Sub «Randomize Timer» - перезагружает таймер случайных чисел. А далее мы объявляем переменную «i», о которой я говорил в начале статьи. При каждом запуске таймера (у нас это каждые 500 миллисекунд - полминуты) она будет объявлена заново. Приравниваем ей значение 0 во избежание ошибок.

pic

Далее идет метка 1 (надеюсь, вы знаете, что такое метка). Далее прибавляем по единице двум переменным и загружаем новую линию.

Загружаем новый элемент — линию с индексом, равным n + 1. Случайным образом выбираем положение линии на форме. Также случайным образом делаем линию видимой. Надо сказать, что у нас будет не линия, а жирная точка, так как X2 = X1, а Y2 = Y1. Теперь проверяем значение «i». Если он еще меньше 10, то идем на метку 1 (ну, вот и узнали, что такое метка!).

Когда все девять разноцветных, жирных точек нарисованы, сменяем цвет лейбла слева вверху (я его именно туда и поставил). Смена цвета тоже происходит случайным образом для привлечения взгляда к «рекламе».

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

Так и сделаем. Сначала обеспечим отключение программы при нажатии на клавишу. Это просто. Какая процедура отвечает за нажатия на кнопки? Правильно, KeyDown:

Private Sub Form_KeyDown (KeyCode As Integer, Shift As Integer)
End
End Sub

Никаких аргументов не проверяем, да это и не надо, а сразу завершаем работу приложения.

А как быть с мышкой? Тут, естественно, нам помогут MouseMove и переменные, которые мы объявили в разделе General.

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If NewLoad = True Then
XX = X
YY = Y
NewLoad = False
Else
XXX = X
YYY = Y
If XX <> XXX Or YY <> YYY Then End
End If
End Sub

Мышка стала очень чувствительной, проверьте.

А теперь полный код скринсейвера:

Option Explicit
Dim n, XX, YY, XXX, YYY As Integer
Dim NewLoad As Boolean
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
End
End Sub
Private Sub Form_Load()
n = 0
NewLoad = True
End Sub
Private Sub Timer1_Timer()
Randomize Timer
Dim i As Integer
i = 0
1:
i = i + 1
n = n + 1
Load L(n)
L(n).X1 = (Me.ScaleWidth * Rnd)
L(n).Y1 = (Me.ScaleHeight * Rnd)
L(n).X2 = L(n).X1
L(n).Y2 = L(n).Y1
L(n).BorderColor = RGB((224 * Rnd), (224 * Rnd), (224 * Rnd))
L(n).Visible = True
If i < 10 Then GoTo 1 Label.ForeColor = RGB((224 * Rnd), (224 * Rnd), (224 * Rnd)) End Sub Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If NewLoad = True Then XX = X YY = Y NewLoad = False Else XXX = X YYY = Y If XX <> XXX Or YY <> YYY Then End
End If
End Sub

И в заключение про то, как можно изменить и оптимизировать скринсейвер. К примеру, если убрать строчку «If i < 10 Then GoTo 1» и уменьшить Interval таймера до 1, то будет рисоваться только одна точка, но очень часто. Тоже красиво. Можно убрать изменения цветов, тогда все будет белым или другого цвета, какого пожелаете. С помощью Me.Line или Me.Point или Me.Circle можно рисовать и другие фигуры. Можно изменять все, что хотите. Кстати, попробуйте добавить фон с картинкой. Сделайте несколько картинок и при каждом запуске скринсейвера выдавайте случайную. Будет интересно, если сделать показ разных изображений в зависимости от времени суток. Утром выдавать зарю и восходящее солнце, в обед - солнце в зените и облака, а вечером - закат с силуэтами птичек у солнца. На сегодня хватит. Будут проблемы, идеи и предложения, пишите -> visualbasic@list.ru Можете зайти на мой сайт http://visualbasic.boom.ru за готовыми исходниками этого скринсейвера.

Приятного программирования.

pic
Orphus system
В Telegram
В Одноклассники
ВКонтакте