217

Delphi учимся на примерах

Embed Size (px)

Citation preview

Page 1: Delphi учимся на примерах
Page 2: Delphi учимся на примерах

С. М. Парижский

чщ

УЧИМСЯ НА ПРИМЕРАХ

Под редакцией Ю. А. Шпака

"МК-Пресс"

Киев, 2005

Page 3: Delphi учимся на примерах

ББК 32.973.26-018.1УДК 681.3.06

П18

Парижский С. М.П18 Delphi. Учимся на примерах/Под ред. Ю. А. Шпака - К.: "МК-Пресс",

2005.-216с, ил.

ISBN 966-8806-02-6

Данная книга — продолжение предыдущей книги автора, "Delphi. Только практика".Также как и в "Delphi. Только практика", в данном издании подробно рассмотрены про-граммы для сетей, различные шуточные программы, простые игрушки, некоторые полез-ные приложения, разработка приложений в стиле Windows XP. В частности, здесь можнонайти такие примеры как бесплатная отправка SMS, FTP-клиент, простое шифрование,CGI-сценарии и многое другое. Описаны методы работы с системным реестром Windows иINI-файлами, а также некоторые важные аспекты программирования на системном уровнес применением функций Windows API. Для облегчения понимания программ каждый при-мер содержит комментарии сложных строк кода.

Книга ориентирована как на тех, кто уже имеет опыт создания приложений в Delphi,так и на начинающих программистов. Для начинающих пользователей Delphi в конце книгидобавлено приложение с описанием синтаксиса языка программирования Object Pascal.

ББК 32.973.26-018.1

Парижский Сергей Михайлович

DelphiУЧИМСЯ НА ПРИМЕРАХ

Главный редактор: Ю. А. ШпакКомпьютерная верстка: Ю. А. Шпак

© Парижский С. М., текст, иллюстрации, 2005I S B N 966—8806—02—6 © "МК-Пресс", оформление, дизайн обложки, 2005

Page 4: Delphi учимся на примерах

Содержание 3

Содержание

ВВЕДЕНИЕ..... 9

ГЛАВА 1. ИНТЕРФЕЙС В СТИЛЕ WINDOWS XP 10

ГЛАВА 2. РАБОТА с ФАЙЛАМИ 13

ПОСТАНОВКА ЗАДАЧИ 13

РАЗРАБОТКА ФОРМЫ 13

РАЗРАБОТКА ПРОГРАММНОГО КОДА 14

Полный исходный код МОДУЛЯ 18

ГЛАВА 3. РАБОТА С ТЕКСТОМ. СТАТИСТИКА ДОКУМЕНТА 22

ПОСТАНОВКА ЗАДАЧИ 22

РАЗРАБОТКА ФОРМЫ 22

РАЗРАБОТКА ПРОГРАММНОГО КОДА 24

Полный исходный код МОДУЛЯ 25

ГЛАВА 4. Снимок ЭКРАНА 29

ПОСТАНОВКА ЗАДАЧИ 29

РАЗРАБОТКА ФОРМЫ 29

РАЗРАБОТКА ПРОГРАММНОГО КОДА 30

ПОЛНЫЙ ИСХОДНЫЙ КОДМОДУЛЯ : 3 I

ГЛАВА 5. ХРАНИТЕЛЬ ЭКРАНА 35

ПОСТАНОВКА ЗАДАЧИ 35

РАЗРАБОТКА ФОРМЫ 35

РАЗРАБОТКА ПРОГРАММНОГО КОДА 37

Полный исходный код МОДУЛЯ 39

ГЛАВА 6. ПРОГРАММА ПРОСМОТРА РИСУНКОВ 43

ПОСТАНОВКА ЗАДАЧИ 43

РАЗРАБОТКА ФОРМЫ 43

РАЗРАБОТКА ПРОГРАММНОГО КОДА 45

Полный исходный код МОДУЛЯ 47

ГЛАВА?. БЛОКНОТ-ШИФРОВАЛЬЩИК 50

ПОСТАНОВКА ЗАДАЧИ 50

РАЗРАБОТКА ФОРМЫ .' 50

РАЗРАБОТКА ПРОГРАММНОГО КОДА 51

Полный исходный код МОДУЛЯ 55

Page 5: Delphi учимся на примерах

Интерфейс в стиле Windows XP

ГЛАВА 8. ИГРА " У С П Е Й ЩЕЛКНУТЬ" 59

ПОСТАНОВКА ЗАДАЧИ 59

РАЗРАБОТКА ФОРМЫ 59

РАЗРАБОТКА ПРОГРАММНОГО КОДА 61

Полный исходный код МОДУЛЯ 63

ГЛАВА 9. ИГРА "УГАДЫВАНИЕ ЧИСЕЛ" 66

ПОСТАНОВКА ЗАДАЧИ 66

РАЗРАБОТКА ФОРМЫ 66

РАЗРАБОТКА ПРОГРАММНОГО КОДА 68

Полный исходный КОДМОДУЛЯ 74

ГЛАВА 10. Вход в СИСТЕМУ 81

ПОСТАНОВКА ЗАДАЧИ 81

РАЗРАБОТКА ФОРМЫ 81

РАЗРАБОТКА ПРОГРАММНОГО КОДА 82

Полный исходный код МОДУЛЯ 86

ГЛАВА 11. ИНФОРМАЦИЯ О ПАМЯТИ 89

ПОСТАНОВКА ЗАДАЧИ 89

РАЗРАБОТКА ФОРМЫ 89

РАЗРАБОТКА ПРОГРАММНОГО КОДА 90

Полный исходный код МОДУЛЯ 91

ГЛАВА 12. ПРОГРАММА НАСТРОЙКИ WINDOWS 95

ПОСТАНОВКА ЗАДАЧИ 95

РАЗРАБОТКА ФОРМЫ 95

РАЗРАБОТКА ПРОГРАММНОГО КОДА 96

Полный исходный КОДМОДУЛЯ 99

ГЛАВА 13. ТЕСТ 103

ПОСТАНОВКА ЗАДАЧИ 103

Структуры базы вопросов и ответов 103

РАЗРАБОТКА ФОРМЫ 104

РАЗРАБОТКА ПРОГРАММНОГО КОДА 106

Полный исходный код МОДУЛЯ 115

ГЛАВА 14. ГЕНЕРАТОР ШУТОК 125

ПОСТАНОВКА ЗАДАЧИ 125

РАЗРАБОТКА ФОРМЫ 125

Page 6: Delphi учимся на примерах

Содержание 5

РАЗРАБОТКА ПРОГРАММНОГО КОДА 125

Шутка №1 — ограничение диапазона движения мыши 127Шутка №2 — отключение кнопок мыши 128Шутка №3 — отключение клавиатуры .....128Шутка №4 — очистка буфера обмена 128Шутка №5 — назначение фона для Рабочего стола 129

Шутка №6 — выбор фона случайным образом 130Шутка №7— выключение монитора 131Шутка №8 — сообщение об ошибке, содержащее "мусор" 131Шутка №9 — открытие браузера Internet Explorer 132Шутка №10 — сброс системной даты/времени 132

Полный исходный код МОДУЛЯ 132

ГЛАВА 15. ОТПРАВКА СООБЩЕНИЙ В ЛОКАЛЬНОЙ СЕТИ 138

ПОСТАНОВКА ЗАДАЧИ 138

РАЗРАБОТКА ФОРМЫ 138

РАЗРАБОТКА ПРОГРАММНОГО КОДА '. 139

Полный исходный код МОДУЛЯ 141

ГЛАВА 16. УДАЛЕННОЕ УПРАВЛЕНИЕ УКАЗАТЕЛЕМ МЫШИ 144

ПОСТАНОВКА ЗАДАЧИ 144

РАЗРАБОТКА КЛИЕНТСКОЙ ПРОГРАММЫ 144

Разработка формы 144Разработка программного кода 145

РАЗРАБОТКА СЕРВЕРНОЙ ПРОГРАММЫ 147

Полный исходный код МОДУЛЕЙ 148

ГЛАВА 17. БЕСПЛАТНАЯ ОТПРАВКА SMS ЧЕРЕЗ INTERNET 152

ПОСТАНОВКА ЗАДАЧИ 152

РАЗРАБОТКА ФОРМЫ 152

РАЗРАБОТКА ПРОГРАММНОГО КОДА 154

Полный исходный код МОДУЛЯ 156

ГЛАВА 18. FTP-КЛИЕНТ 158

ПОСТАНОВКА ЗАДАЧИ 158

РАЗРАБОТКА ФОРМЫ 158

РАЗРАБОТКА ПРОГРАММНОГО КОДА 161

Полный исходный код МОДУЛЯ 165

Page 7: Delphi учимся на примерах

Интерфейс в стиле Windows XP

ГЛАВА 19. НАПИСАНИЕ CGI-ПРИЛОЖЕНИЙ 171

ПОСТАНОВКА ЗАДАЧИ 171

РАЗРАБОТКА ПРОЕКТА 171

ПРИЛОЖЕНИЕ А. Коды КЛАВИШ И ИХ ЗНАЧЕНИЯ 174

ПРИЛОЖЕНИЕ Б. KYLIX — DELPHI ДЛЯ LINUX 177

ПРИЛОЖЕНИЕ В. СПРАВОЧНИК по РЕЕСТРУ WINDOWS 178

ОБЩАЯ НАСТРОЙКА ПК 178

Изменение разрешения экрана 178

Установка задержки перед появлением контекстного меню 178

Сокрытие изображение стрелки на ярлыках 178

Сокрытие приставки "Ярлык для... " 179

Запрет на редактирование реестра 179

Отключение динамика ПК 179

Включение динамика ПК 179

Отключение возможности автозапуска с CD-ROM. 179

Отключение всплывающих подсказок в Проводнике и

на Рабочем столе 180

Автоматическое наведение указателя мыши на активную кнопку. 180

Отключение возможности открывать диспетчер задач 180

Отключение возможности восстановления системы 180

Очистка swap при выключении компьютера. 180

ИЗМЕНЕНИЕ РАЗМЕЩЕНИЯ ПАПОК и КАТАЛОГОВ 181

Изменение размещения папки Избранное 181

Изменение каталога по умолчанию для программ 181

СОКРЫТИЕ ПУНКТОВ СИСТЕМНОГО МЕНЮ ПУСК 181

Сокрытие пункта Пуск —> Найти 181

Сокрытие пункта Пуск —» Программы —> Стандартные 181

С окры тие пункта Пуск —» Избранное 181

Сокрытие пункта Пуск —> Документы 182

Сокрытие пункта Пуск —> Панель управления 182

Сокрытие пункта Пуск—* Выполнить 182

Сокрытие пункта Пуск -> Настройка -» Принтеры 182

Сокрытие пункта Пуск—> Настройка —> Панель задач 182

Сокрытие пункта Пуск —> Завершение сеанса 183

Сокрытие пункта Пуск^> Выключить компьютер 183

Сокрытие всех дополнительных папок в меню Пуск 183

Page 8: Delphi учимся на примерах

Содержание 7

Сокрытие папки Мои документы в меню Пуск. 183

СОКРЫТИЕ РАЗЛИЧНЫХ ЭЛЕМЕНТОВ ИНТЕРФЕЙСА 183

Сокрытие дисков в папке Мой компьютер 183

Сокрытие пиктограммы Принтеры в панели управления 184

Сокрытие вкладок Общие и Сведения в окне свойств принтера 185

НАСТРОЙКА РАБОЧЕГО СТОЛА 185

Сокрытие всех элементов Рабочего стола /55

Сокрытие пиктограммы Internet на Рабочем столе „ 185

Сокрытие пиктограммы Сетевое окружение на Рабочем столе 185

Отключение возможности вызывать окно свойств экрана 185

Отключение контекстного меню панели задач 186

Отключение контекстного меню Рабочего стола 186

Сокрытие папки Мои документы на Рабочем столе 186

СОКРЫТИЕ ВКЛАДОК ОКНА свойств ЭКРАНА 186

Сокрытие вкладки Оформление 186

Сокрытие вкладки Фон 186

Сокрытие вкладки Заставка 187

Сокрытие вкладки Параметры 187

НАСТРОЙКА БРАУЗЕРА INTERNET EXPLORER : 187

Сокрытие команд меню, кнопок и панелей 187

Сокрытие элементов окна Свойства обозревателя 189

Общая настройка браузера 190

ПРИЛОЖЕНИЕ Г. Язык OBJECT PASCAL 195

КОММЕНТАРИИ 195

ИДЕНТИФИКАТОРЫ 195

ВСТРОЕННЫЕ типы ДАННЫХ 196

Числовые типы 196

Символьный тип 197

Строковые типы 197

Булев тип данных 197

Массивы 197

КОНСТАНТЫ 198

ПЕРЕМЕННЫЕ 198

ПОЛЬЗОВАТЕЛЬСКИЕ ТИПЫ ДАННЫХ 199

Множества 199

Перечислимые типы 200

Подтипы 201

Page 9: Delphi учимся на примерах

Интерфейс в стиле Windows XP

ЗАПИСИ 201

КЛАССЫ 202

Определение членов класса 202

Свойства класса 204

Методы класса 205

КОНСТРУКЦИЯ WITH-DO 205

СТРУКТУРА ПРОЕКТА DELPHI 206

Файл проекта . dpr 206

Файл программного модуля .pas 207

ПРОЦЕДУРЫ И ФУНКЦИИ 208

Параметры 208

Вызов процедур и функций 209

Досрочный выход из процедуры или функции 209

ОПЕРАТОРЫ 209

Оператор присваивания 210

Арифметические операторы 210

Булевы операторы 210

Операторы сравнения 210

Побитовые операторы 210

Строковые операторы 211

Операторы, применяемые к множествам 211

Операторы, применяемые с объектами 211

Группировка операторов 212

Порядок выполнения операторов 212

БЛОКИ ПРОГРАММНОГО КОДА 2 1 2

КОНСТРУКЦИИ ВЕТВЛЕНИЯ 212

Оператор if, 212

Оператор case 213

ЦИКЛИЧЕСКИЕ КОНСТРУКЦИИ 213

Конструкция for-do 213

Конструкция while-do 214

Конструкция repeat-until 214

Досрочный выход из циклов 214

ОБРАБОТКА ИСКЛЮЧЕНИЙ 214

Блок операторов finally 216

Page 10: Delphi учимся на примерах

Введение 9

ВведениеВ своей первой книге, "Delphi. Только практика", автор рассмат-

ривал примеры различных интересных программ. Эта книга являетсяпродолжением первой книги. Продолжением, поскольку исходные кодыпрограмм, которые рассматриваются в первой и второй книге, не повто-ряются. Также как и в "Delphi. Только практика", в данном изданииподробно рассмотрены программы для сетей, различные шуточные про-граммы, простые игрушки, некоторые полезные приложения, разработ-ка приложений в стиле Windows XP. В частности, здесь можно найтитакие примеры как бесплатная отправка SMS, FTP-клиент, простоешифрование, CGI-сценарии и многое другое.

Поскольку рассмотренные примеры достаточно просты, то даже на-чинающий программист сможет быстро освоить азы написания прило-жений в Delphi и перейти к разработке собственных проектов (описаниесинтаксиса языка программирования Object Pascal представлено в при-ложении Г). Само собой разумеется, что для изучения изложенногов книге материала желательно знать основы работы с Windows, по-скольку Delphi — средство разработки программ именно для этой опе-рационной системы.

Структура книги такова, что ее не обязательно читать от начала доконца, — можно просто открыть любую главу и разработать рассматри-ваемую программу. Все примеры подробно объясняются и содержаткомментарии сложных строк кода. Книга будет интересна как опытнымпрограммистам, так и тем, кто только начал изучать язык программиро-вания Delphi.

К книге прилагается компакт-диск, содержащий исходные и ис-полняемые файлы всех рассмотренных программ, а также цветные ко-пии рисунков.

Page 11: Delphi учимся на примерах

10 Интерфейс в стиле Windows XP

Глава 1

Интерфейс в стиле Windows XP

Как известно, интерфейс программ, написанных на Delphi и запус-каемых в операционной системе (ОС) Windows XP, при любом стилеоформления будет иметь одинаковый вид. В этой главе будет показанокак написать программу, которая будет отображаться в стиле ХР.

С помощью любого редактора создайте текстовый файл и введитев нем следующий текст:<?xml version="l.О" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.vl"manifestVersion="l.0"><assemblyldentity

name="Microsoft.Windows.ApplicationName"processorArchitecture="x8 6"version="l.0.0.0"type="win32"/>

<description>ApplicationDescription</description><dependency>

<dependentAssembly><assemblyldentity

type="win32"

name="Microsoft.Windows.Common-Controls"version="6.0.0.0"processorArchitecture="x8 6"publicKeyToken="6595b6414 4ccfldf"language="*"

</dependentAssemblу></dependency>

</assembly>

Сохраните этот файл под именем с: \xp_style . txt . Затем создай-те еще один текстовый файл следующего содержания:[Т~2Т~сТ\xp_style.txt

Сохраните этот файл под именем xp_style.rc в каталогеC:\Program file\Delphi\Bin.

Page 12: Delphi учимся на примерах

Введение 11

Файлы x p _ s t y l e . t x t и x p _ s t y l e . r e можно найти на прилагаемом к книгекомпакт-диске в папке C h a p t e r 0 1 .

ПримечаниеУказанный выше путь к папке B i n предполагает, что Delphi был установленв каталог, выбранный по умолчанию. Если при установке был выбран другой ката-лог, то используйте именно его. Далее в книге будет везде использован путь поумолчанию.

Теперь запустим программу C:\Program f i le\Delphi\Bin\brcc32 . ехе, передав ей в качестве параметра имя файла хр s t y l e . re.Для этого следует перейти в режим командной строки, выполнив ко-манду системного меню Пуск • Выполнить, а затем в диалоговом окнеЗапуск программы введя команду cmd и нажав клавишу <Enter>. В ре-жиме командной строки с помощью команды cd перейдем в каталогС: \Program f i le\Delphi\Bin и выполним следующую команду:brcc32.exe xp_style.rc

В результате в каталоге C:\Program f i l e\Delphi\Bin долженпоявиться ресурсный файл x p s t y l e . res , который следует подклю-чать к приложению в том случае, когда его требуется оформить в стилеWindows XP.

Проверим, так ли это, создав программу в стиле ХР. Откройте диа-логовое окно настройки свойств Рабочего стола и выберите тему Win-dows ХР (если она еще не выбрана).

Создайте в Delphi новый проект и разместите на форме компонентEdit категории Standard. Присвойте его свойству Text следующее зна-чение: Все компоненты и сама форма в стиле Windows ХР. Нижеразместите кнопку (компонент Button категории Standard), при нажа-тии которой будет появляться информационное окно (оно тоже должно

_Х1 :̂̂ Обработ^чик события ОпС 1 i с к для КНОПКИ:

procedure TForml.ButtonlClick(Sender: TObject);

begin

ShowMessage(Editl.Text);

end;

Теперь при нажатии КНОПКИ будет появляться окно, содержащеетекст, извлеченный из поля для ввода. Запустим программу на выпол-нение. Как видим, внешний вид интерфейса никак не изменился, несмотря на то, что выбрана тема Windows ХР.

Page 13: Delphi учимся на примерах

12 Интерфейс в стиле Windows XP

Для того чтобы решить эту проблему найдите в программном моду-

ле раздел i m p l e m e n t a t i o n (сейчас в нем указано только подключение

файла формы *.dfm при помощи директивы {$R *.dfm}). Для того

чтобы подключить наш файл ресурсов, следует в разделе i m p l e m e n t a -

t ion ^2^3^—^915.9Ш1 ; ____.($R x p _ s t y l e . r e s }

Теперь можно запустить программу и насладиться интерфейсом ХР

(рис. 1.1).

Все компоненты и сама форма в стиле ХР

Рис. 1.1. Элементы формы отображаются в стиле Windows ХР

Введите в поле какой-либо текст и нажмите кнопку — должно поя-

виться информационное окно, которое также будет отображаться в сти-

ле Windows ХР (рис. 1.2). При этом, размер ехе-файла увеличился всего

лишь на несколько сотен байт.

Все компоненты и сама форма в стиле ХР

Рис. 1.2. Информационное окно также отображается в стиле Windows ХР

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 0 1 .

Page 14: Delphi учимся на примерах

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

Глава 2

Работа с файлами

Постановка задачиРазработать программу для работы с файлами. Программа должна

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

Разработка формыСоздайте новый проект Delphi. Первым делом разработаем интер-

фейс программы. Изменим некоторые свойства главной формы. Преждевсего, присвойте соответствующее значение свойству Caption (заголо-вок формы) — например, Работа с файлами. Поскольку окно нашейпрограммы должно всегда находиться поверх всех остальных окон, сле-дует присвоить свойству FormStyle значение fsStayOnTop. Большеникаких свойств формы изменять не будем.

Разместите в левом верхнем углу формы, один над другим два ком-понента Label (метка) категории Standard. Для верхней метки присвой-те свойству Caption значение Что:, а для второй - - Куда:. Рядом сметками разместите по одному компоненту Edit (поле ввода) категорииStandard. Присвойте свойству Name (имя) верхнего поля значение from,а свойству Name нижнего — значение where. Свойствам from.Text иwhere. Text присвойте пути по умолчанию, например: c : \ L t x t иd i \ 2 . t x t .

Для того чтобы не утруждать пользователя копированием или руч-ным вводом путей размещения файлов, воспользуемся стандартнымидиалоговыми окнами открытия и сохранения файлов. Диалоговом окнуоткрытия файла соответствует компонент OpenDialog категории Dia-logs, а диалоговому окну сохранения — компонент SaveDialog той жекатегории. Разместим эти компоненты на форме. Для удобства изменимзначение свойства OpenDialogl.Name на Openl, а значение свойстваSaveDialogl,Name на Savel.

Page 15: Delphi учимся на примерах

14 Работа с файлами

Справа от полей from и where разместим кнопки вызова диалого-вого окна обзора (компоненты Button категории Standard). СвойствуCaption этих кнопок присвойте значение Обзор или просто поставьтеточки. При желании, можете изменить размеры кнопок.

Разместите на форме под полем where компонент Label категорииStandard и присвойте его свойству Caption значение Размер файла:.Справа от этой метки разместите еще один компонент Label, очистивдля нее свойство Caption — эта метка будет отображать размер обра-батываемого файла.

Ниже разместим две кнопки (компоненты Button), присвоим ихсвойствам Caption значения Копировать и Вырезать. Под этимикнопками разместим компоненты, которые будут использоваться длявыбора и удаления файлов: компонент Edit для ввода пути к файлу,кнопка вызова диалогового окна обзора и кнопка для удаления файла.

Свойству Editl.Name присвоим значение Del, а свойству Text -путь по умолчанию. Кнопку Обзор разместим справа, а кнопку Удалитьфайл — под полем Del.

Полученная форма должна соответствовать рис. 2.1.

р•Работа с файлами

Что: • ICA1.txt

Куда: • D: V2.txt

Размер файла:

Копировать Вырезать

D:\1.txt

Удалить Файл

Рис. 2.1. Форма Работа с файлами

Разработка программного кодаРазработаем процедуру копирования файла. Это можно было бы

реализовать средствами WinAPI, однако в этом случае процедура, хотя

Page 16: Delphi учимся на примерах

Разработка программного кода 15

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

Для начала объявим нашу процедуру (назовем ее doit) как закрытыйчлен класса формы:

typeTFormi = class(TForm)

private{ Private declarations }procedure doit;

public{ Public declarations }

end;

Реализацию процедуры создадим в разделе implementation:

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

i

procedure TFormi.doit();var

f1, f 2 : file of Byte; //Работа с первым и вторым файломсор: Byte; //Для побайтового копированияsizez: Longlnt; //Хранит размер файла

begin{$1-} //Отключаем директиву, которая отслеживает ошибки

//ввода/выводаtry //Начало блока обработки исключений

//Связываем файловую переменную fl с первым файломAssignFile(fl, from.Text);//Связываем файловую переменную f2 со вторым файломAssignFile(f2, where.Text);

Reset(fl); //Открываем первый файл на чтениеsizez := Trunc(FileSize(f1)); //Определяем размер файла//Отображаем размер файл для пользователяLabel4.Caption := IntToStr(sizez div 1024) + 'Кб

1;

(Создаем второй файл или перезаписываем его, если он ужесуществует}

Rewrite(£2);while not Eof (fl) dobegin //Пока не достигнут конец первого файла

//Считываем один байт из первого файлаBlockRead(fl, cop, 1);//Записываем один байт во второй файл

Page 17: Delphi учимся на примерах

16 Работа с файлами

BlockWrite(f2,cop,1);

end;

CloseFile(fl); //Закрываем первый файлCloseFile(f2); //Закрываем второй файл

finally;

end; //Конец блока обработки исключенийif IOResult <> 0 //Если возникла ошибка ввода-вывода

then MessageDlg('Ошибка при копировании файла!',

mtError, [mbOk],0) //сообщение об ошибкеelse begin

{Если ошибок не было, то выводим окно об успешномокончании копирования)

ShowMessage('Успешно скопировано!');

L end;

end;

Различные конструкции языка Object Pascal (комментарии, операторы ветвления,обработка исключений и др.) рассматриваются в приложении Г.

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

Процедура d o i t вызывается при нажатии кнопки Копировать:procedure TForml.ButtonlClick{Sender: TObiect);

По нажатию кнопки Вырезать должно происходить обычное копи-ювание с последующим удалением скопированного файла:procedure TForml.Button5Click(Sender: TObject);begin

doit; //копируемDeleteFile(from.Text); //удаляем исходный файл

end;

Теперь создадим процедуры выбора и сохранения файла с помощьюстандартных диалоговых окон. Для выбора первого (исходного) файласледует создать следующий обработчик события OnClick (кнопке But-ton2 соответствует поле from):[procedure TForml. Button2Click (Sender: TObjectTl •—•••••••••••••• ~ ~ j

Page 18: Delphi учимся на примерах

Разработка программного кода 17

beginif Openl.Execute

then from.Text :=

else ShowMessage(

end;

Openl

'Файл.FileName

не был открыт');

При нажатии кнопки Обзор открывается диалоговое окно выборафайла (Openl. Execute). Если в этом окне пользователь нажал кнопкуОтмена (Openl. Execute = False), то сообщаем ему об этом и не вы-полняем никаких действий. Если пользователь выбрал файл, то копиру-ем путь к нему в соответствующее поле ввода.

Создадим аналогичный обработчик события для выбора пути на-значения при копировании первого файла (кнопке Button3 соответст-вует поле where):procedure TForml.Button3Click(Sender:begin

if Savel.Executethen where.Text :=

else ShowMessage('

end;

Savel.FileName

TObject);

Вы не выбрали место для сохранения файла! ') ;

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

Теперь создадим аналогичный обработчик события OnClick для

[procedure TForml.Button4Click(Sender: TObject);I begin

if Openl.Execute

then Del.Text := Openl.FileName

else ShowMessage('Файл не был открыт!');

procedure TForml.Button6Click(Sender: TObject);begin

DeleteFile(Del.Text); //удаляем файлif not FileExists(Del.Text) //проверяем существование файла

then ShowMessage('Файл удален!'); //выводим сообщениеend;

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

2 — 5-1212

Page 19: Delphi учимся на примерах

18 Работа с файлами

компилировать и запустить программу на выполнение. Внешний вид

окна Работа с файлами в действии показан на рис. 2.2.

i f Работа с файлами ш1Р\ X

Что: JCADocuments and Settings'1^ее1\Рабоч

Куда: |5лРго1ес(.еке

Размер файла: 389Кб

Копировать Вырезать

I D:\Projectexej

Удалить файл

Рис. 2.2. Программа Работа с файлами в действии

Полный исходный код модуляПолный код модуля программы Работа с файлами представлен

в листинге 2.1.

Листинг 2.1. Модуль программы Работа с файлами

unit Unitl;

interface

usesWindows,Controls,

typeTForml =

Messages, SysUtils, Variants, Classes, Graphics,Forms, Dialogs, StdCtrls, ShellAPI, Gauges;

class(TForm)from: TEdit;where:ButtonlLabell:Label2:Label3:Label4:

TEdit;: TButton;TLabel;TLabel;TLabel;:TLabel;

Page 20: Delphi учимся на примерах

Полный исходный код модуля 19

Листинг 2.1. Продолжение

Button2: TButton;Button3: TButton;Openl: TOpenDialog;Savel: TSaveDialog;Button4: TButton;del: TEdit;Button5: TButton;Button6: TButton;procedure ButtonlClick(Sender: TObject)procedure Button2Click(Sender: TObject)procedure Button3Click(Sender: TObject)procedure Button5Click(Sender: TObject)procedure Button4Click(Sender: TObject)procedure Button6Click(Sender: TObjent)

private( Private declarations }procedure doit; //объявление процедуры doit

public{ Public declarations }

end ;

var Forml: TForml;

implementation

{$R *.dfm}

procedure Tforml.doit() ;var

fl,f2: file of byte; //работа с первым и вторым файломсор: byte; //для побайтового копированияsizez: longint; //хранит размер файла

begin{$1-} {отключаем директиву, которая следит за ошибками

ввода/вывода}try

//связываем Файловую переменную fl с первым файломAssignFile(fI, from.Text);//связываем файловую переменную f2 со вторым файломAssignFile(f2, where.Text);Reset(fl); //открываем первый файл на чтениеsizez := Trunc(FileSize(f1)); //узнаем размер файла//Отображаем размер файл для пользователя}Label4.Caption := IntToStr(sizez div 1024) + 'Кб

1;

{Создаем второй файл или перезаписываем его, если онуже существует}

2* ~~~ " ~™~

Page 21: Delphi учимся на примерах

20 Работа с файлами

Листинг 2,1. Продолжение

Rewrite(f2);while not Eof(fl) dobegin //пока не достигнут конец первого файла

//считываем один байт с первого файлаBlockRead(fl, cop, 1);//записываем один байт во второй файлBlockWrite(f2, cop, 1);

end;

CloseFile(f1); //закрываем первый файлCloseFile(f2);// закрываем второй файл

finally;end;

if IOResult <> 0 //Если возникла ошибка ввода-выводаthen MessageDlg('Ошибка при копировании файла! ',

mtError, [mbOk],0) //сообщение об ошибкеelse begin

[если ошибок не было, то выводим окно об успешномокончании копирования}ShowMessage('Успешно скопировано!');

end;end;

procedure TForml.ButtonlClick(Sender: TObject);begin

doit;end;

procedure TForml.Button2Click(Sender: TObject);begin

if Openl.Execute then from.Text := Openl.FileName

else ShowMessage('Файл не был открыт');end;

procedure TForml.Button3Click(Sender: TObject);begin

if Savel.Execute then where.Text := Savel.FileNameelse

ShowMessage(''Вы не выбрали место для сохранения файла!1;

end;

procedure TForml.Button5Click(Sender: TObject);begin

doit;DeleteFile(from.Text); //удаляем исходный файл

end;

Page 22: Delphi учимся на примерах

Полный исходный код модуля 21

Листинг 2.1. Окончание

procedure TForml.Button4Click(Sender: TObject);begin

if Openl.Execute then del.Text := Openl.FileNameelse ShowMessage('Файл не был выбран

1);

end;

procedure TForml.Button6Click(Sender: TObject);begin

DeleteFile(del.Text); //удаляем файлif not FileExists(del.Text)

then //проверяем существование файла-//выводим сообщение об,успешном удаленииShowMessage('Файл удален!') ;

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ 0 2 .

Page 23: Delphi учимся на примерах

22 Работа с текстом. Статистика документа

Глава 3 ____

Работа с текстом. Статистикадокумента

Постановка задачиРазработать программу, которая выводит статистику выбранного

пользователем документа. Статистические данные включают в себя ко-личество слов, символов, пробелов и строк.

Разработка формыСоздадим новый проект Delphi и разработаем интерфейс програм-

мы. Измените значение свойства Caption главной формы на Стати-стика. Разместите на форме компонент Label категории Standard, иприсвойте его свойствам значения согласно табл. 3.1.

Таблица 3.1. Свойства компонента L a b e l , размещенного на форме Статистика

Свойство

Capt ion

Font .Color

Font.Name

F o n t . S i z e

F o n t . S t y l e

L e f t

Top

Значение

Статистика

clRed

Cour ier New

16

[ f s B o l d ]

128

8

Пояснение

Надпись метки

Цвет надписи — красный

Шрифт надписи

Размер шрифта надписи

Стиль шрифта — полужирный

Отступ слева

Отступ сверху

Ниже разместите компонент Edit категории Standard (поле ввода),в котором будет храниться путь к обрабатываемому файлу. Справа отнего разместим кнопку (компонент Button категории Standard), котораябудет открывать окно обзора для выбора файла. Присвойте свойствуB u t t o n l . C a p t i o n значение Обзор.

Для реализации выбора файла разместите на форме компонентOpenDialog категории Dialogs. Измените значение свойства Name этогокомпонента на Openl.

Page 24: Delphi учимся на примерах

Разработка формы 23

Разместите на форме четыре компонента Label и присвойте ихсвойству Caption значения Слов, Символов, Пробелов и Строк. Рас-положите эти метки одну над другой вдоль левого края формы и уста-новите свойства шрифта согласно табл. 3.2.

Таблица 3.2. Свойства шрифта компонентов L a b e l

Свойство

Font.Name

Font.S ize

F o n t . S t y l e

Значение

Cour ier New

12

[ f s B o l d ]

Пояснение

Шрифт надписи

Размер шрифта надписи

Стиль шрифта — полужирный

Разместите на форме справа от каждого предыдущих четырех метокеще четыре компонента Label и присвойте им имена (свойство Name)words, symbols, spaces и l i n e s . Присвойте значения свойствам этихметок согласно табл. 3.3.

Таблица 3.3. Свойства компонентов w o r d s , s y m b o l s , s p a c e s и l i n e s

Свойство

Caption

Font .Color

Font.Name

Font.S ize

F o n t . S t y l e

L e f t

Значение

0

clRed

Courier New

12

[fsBold]

112

Пояснение

Надпись метки

Цвет надписи — красный

Шрифт надписи

Размер шрифта надписи

Стиль шрифта — полужирный

Отступ слева

В првом нижнем углу формы разметим кнопку (компонент Button),по нажатию которой будут выполняться рассчеты и выводиться все дан-ные. Свойству Caption этой кнопки присвоим значение Статистика.На этом разработка формы завершена. Полученный результат долженпримерно соответствовать рис. 3.1.

I B Статистика

: Щ:Слов:

Символов:

• Пробелов:

Строк:

•' 0

: 0

: Р.

С т а т и с т и к а : . : : : : : : : : : : . : : • :

; ; 1 cAautoeKec.bat Обзор...

Статистика

Рис. 3.1. Форма Статистика

Page 25: Delphi учимся на примерах

24 Работа с текстом. Статистика документа

Разработка программного кодаВ этой программе следует обработать только два события: нажатие

кнопки Обзор и нажатие кнопки Статистика. Сначала — о кнопке Обзор:procedure TForml.ButtonlClick(Sender: TObject);begin

//начинаем обзор с текущей папкиOpenl.InitialDir := GetCurrentDir;

if Openl.Execute

then Editl.Text : = Openl.FileName //открываем диалоговое//окно выбора файла

else ShowMessage('Файл не выбран!');[end;

Начинаем обзор с каталога, в котором в данный момент находитсяпрограмма. Затем следует стандартная проверка: если файл не был вы-бран, то сообщаем об этом пользователю, иначе отображаем путь к фай-лу в поле E d i t l .

При нажатии кнопки Статистика выполняется подсчет и отображе-

jprocedure TForml.Button2Click(Sender: TObject);j var

f: file of byte; //Переменная для работы с файломstr: byte; //Содержит считанный байтoldstr, symbol, word, line, space: Integer; //Стат. данные

begin

symbol := 0; //обнуляем предыдущие результатыword := 0;

space := 0;

line := 0;if FileExists(Editl.Text) //проверяем, существует ли файлthen begin

AssignFile(f,Editl.Text); //связываем файл с переменной fReset (f) ; //открываем файл на чтениеwhile not Eof (f) dobegin //читаем файл до достижения конца файла

oldstr := str;

Read(f, str); //считываем символ в переменную strif ((str <> 32) and (str <> 13) and (str <> 10))

then symbol := symbol + 1; {пополняем количествосимволов, если он не является переводомстроки, кодом новой строки или пробелом}

//если считан пробел, пополним счетчик пробеловif str = 32 then space := space + 1;

if str = 13 then line := line + 1; //счетчик строкif ((str = 32) or (str = 13) or (str = 10)) then

Page 26: Delphi учимся на примерах

Полный исходный код модуля 25

if <(oldstr<>32) and (oldstrOlO) and (oldstr<>13) )then word := word + 1; //счетчик слов

end;

CloseFile(f); //закрываем файлend

else ShowMessage('Ошибка: Файл не найден!'); {если файл ненайден, то выводим сообщение об ошибке}

//Выводим всю полученную информацию о файлеsymbols.Caption :• IntToStr(symbol);spaces.Caption := IntToStr(space);lines.Caption := IntToStr(line);words.Caption := IntToStr (word) ;

end;

Сначала мы проверяем, существует ли файл, статистику которогобудем определять. Если все нормально, то начинаем считывать из этогофайла по одному символу и проверять по коду, что это за символ. Есликод символа равен 32, то это — пробел, и мы пополняем счетчик пробе-лов. Если код считанного символа равен 13, то это •— символ переводастроки, и мы пополняем счетчик строк. Если считанный символ не яв-ляется пробелом или символом перевода строки, то это - - обычныйсимвол и следует пополнить счетчик символов. Для того чтобы подсчи-тать количество слов, мы выполняем следующую проверку: если считанпробел или символ перевода строки, то проверяем, является ли преды-дущий символ пробелом или символом перевода строки, и если это так,пополняем счетчик слов.

Результат выполнения программы представлен на рис. 3.2.

Статистика

СтатистикаСлов: 161

Символов: 1317

Пробелов: 173

Строк: 79

DADocsVrexl\Delphi\Unit1.pa

Статистика

Рис. 3.2. Программа Статистика в действии

Полный исходный код модуляКод модуля программы Статистика представлен в листинге 3.1.

Page 27: Delphi учимся на примерах

26 Работа с текстом. Статистика документа

Листинг 3.1. Модуль программы СтатистикаГ unit Unitl;

interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, StdCtrls;

typeTForml -

LabellLabei2

Label3Label4

Label5words:

class(TFormTLabel;TLabel;TLabel;

TLabel;TLabel;

TLabel;

spaces

symbols: TLabel;

TLabel;lines: TLabel;Buttonl: TButton;Editl: TEdit;Button2: TButton;Openl: TOpenDialog;procedure ButtonlClick(Sender: TObject);procedure Button2Click(Sender: TObject);

private

{ Private declarations }public

{ Public .declarations }end;

var Forml: TForml;

[ implementation

{$R *.dfm}

procedure TForml.ButtonlClick(Sender: TObject);begin

//начинаем обзор с текущей папкиOpenl.InitialDir := GetCurrentDir;if Openl.Execute // открываем диалоговое окно выбора файла

then Editl.Text := Openl.FileNameelse ShowMessage('Файл не выбран!');

end;

Page 28: Delphi учимся на примерах

Полный исходный код модуля 27

Листинг 3.1. Окончание

procedure TForml.Button2Click(Sender: TObject);var

f: file of byte; //Переменная для работы с файломstr: byte; //Содержит считанный байтoldstr, symbol, word, line, space: Integer;

beginsymbol := 0; //обнуляем предыдущие результатыword := 0;space := 0;line := 0;if FileExists(Editl.Text) //проверяем, существует ли файлthen beginAssignFile(f,Editl.Text); //связываем файл с переменной fReset (f); //открываем файл на чтениеwhile not Eof(f) dobegin //читаем файл до достижения конца файла

oldstr := str;Read(f, str); //считываем символ в переменную strif ((str <> 32) and (str о 13) and (str <> 10))

then symbol := symbol + 1; (пополняем количествосимволов, если он не является переводомстроки, кодом новой строки или пробелом}

//если считан пробел, пополним счетчик пробеловif str = 32 then space := space + 1;if str = 13 then line := line + 1; //счетчик строкif ((str = 32) or (str = 13) or (str = 10)) then

if ((oldstr<>32) and (oldstrOlO) and (oldstr<>13))then word := word + 1; //счетчик слов

end;CloseFile(f); //закрываем файл

endelse ShowMessage('Ошибка: Файл не найден!'); {если файл не

найден, то выводим сообщение об ошибке}symbols.Caption := IntToStr(symbol); //Выводим всюspaces.Caption := IntToStr(space); //полученнуюlines.Caption := IntToStr(line); //информацию о файлеwords.Caption := IntToStr(word);

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ 0 3 .

Page 29: Delphi учимся на примерах

28 Снимок экрана

Глава 4

Снимок экрана

Постановка задачиРазработать программу, которая будет снимать и сохранять копию

экрана.

Разработка формыСоздайте новый проект Delphi и измените заголовок формы (свой-

ство Caption) на Screenshot. Чтобы пользователь не мог изменятьразмеры окна при работе с программой, следует присвоить свойствуBorderStyle значение bsDialog. Для удобства создания копий экранаокно программы должно быть всегда размещено поверх остальныхокон. Для этого присвоим свойству FormStyle значение f sStayOnTop.Мы можем себе это позволить: на самой копии экрана окно нашей про-граммы отображено не будет, поскольку в момент создания копии онобудет временно сокрыто.

Для сохранения копии экрана нам понадобится компонентSaveDialog категории Dialogs. Разместите этот компонент на форме.Поскольку мы заранее знаем, что будем сохранять рисунок, то свойствуSaveDialogl . F i l t e r присвойте значение Рисунок | * . bmp | Все фай-лы! * .*. При сохранении файла у пользователя будет выбор: сохранятьфайл как рисунок (.* . bmp) или как любой другой файл (***).

Разместите вдоль правого края формы четыре кнопки (компонентыButton категории Standard) со следующими заголовками (свойствоCaption): Сделать снимок экрана, Показать снимок, Очистить иСохранить. Также нам потребуется компонент, который будет отобра-жать полученную копию экрана. Для этих целей мы будем использоватькомпонент Image категории Additional. Измените его имя (свойствоName) на Screenl , а свойству P r o p o r t i o n a l присвоим значение True.

На этом разработка формы завершена. Полученный результат дол-жен примерно соответствовать рис. 4.1.

Page 30: Delphi учимся на примерах

Разработка программного кода 29

• ScreenShot*

Показать снимок

Очистить

СохранитьJ

Рис. 4.1. Форма для создания копий экрана

Разработка программного кодаДля начала объявим все переменные, которыми будем пользоваться

в nE°£P?Mi^£L_ _____ _гагForml: TForml; //главная формаВМР1: Graphics.TBitmap; //для работы с рисунками (*.bmp)DC1: HDC; //простое поле для графикиImagel: TImage;

Самое главное событие в программе это нажатие кнопки Сделать

procedure TForml.ButtonlClick(Sender: TObject);beginForml.Visible := False; //прячем формуSleep(15); //пауза 15 мсBMP1 := Graphics.TBitmap.Create;//задаем размеры рисунка такие же как размеры экранаВМР1.Height := Screen.Height;ВМР1.Width := Screen.Width;DC1 := GetDC(O);

//Делаем копию экранаBitBlt(BMPl.Canvas.Handle, 0, 0, Screen.Width,

Screen.Height, DC1, 0, 0, SRCCOPY);

Forml.Visible := True; //восстанавливаем окно программыImagel := TImage.Create(nil);BMP1.IgnorePalette := True;

Imagel.Picture.Assign(BMP1);

Page 31: Delphi учимся на примерах

30 Снимок экрана

ВМР1.SaveToFile('с:\1.bmp1); //сохраняем снимок в файл

//l.bmp на диске С:\

end;

Перед тем как сделать снимок экрана, мы прячем окно программы,делаем паузу в 15 мс и задаем размеры будущего рисунка. После этогоделаем снимок экрана и сохраняем его в файл 1. bmp, который находит-ся на диске С: \.

^ к о д :

procedure TForml.Button4Click(Sender: TObject);begin

Screenl.Show; // делаем рисунок видимымif FileExists('с:\1.bmp

1) then //если рисунок существует,

Screenl.Picture.LoadFromFile('c:\1.bmp'); //загружаем егоend;

По нажатию кнопки Очистить мы должны скрывать рисунок и уда-лять его с диска:procedure TForml.Button3Click(Sender: TObject);begin

//удаляем рисунок с дискаif FileExists('с:\1.bmp

1) then DeleteFile('С:\1.bmp');

Screenl.Hide; //скрываем рисунокend;

Для сохранения рисунка будем использовать диалоговое окно. Код

нажатия кнопки Сохранить:

procedure TForml.Button2Click(Sender: TObject);begin

if SaveDialogl.Execute then

BMP1.SaveToFile(SaveDialogl.FileName) //сохраняем рисунокelse ShowMessage('Файл не был сохранен!

1);

end;

Здесь мы проверяем, выбрал ли пользователь место сохраненияфайла. Если да, то сохраняем рисунок по указанному расположению.

Откомпилируем и запустим программу на выполнение (резуль-тат — на рис. 4.2).

Полный исходный код модуляПолный исходный код модуля программы ScreenShot представлен

в листинге 4.1.

Page 32: Delphi учимся на примерах

Полный исходный код модуля 31

Э5ЭЗВЗЯИ

ИГ— ^•

xj

Сделать снимок экрана

Показать снимок

Очистить

Сохранить

Рис. 4.2. Программа ScreenShot в действии

Листинг 4.1. Модуль программы ScreenShot

unit Unitl;

interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Registry,WinProcs, jpeg;

typeTForml = class(TForm)

Buttonl: TButton;Button2: TButton;Screenl: TImage;SaveDialogl: TSaveDialog;Button3: TButton;Button4: TButton;procedure ButtonlClick(Sender:procedure Button2Click(Sender:procedure Button3Click(Sender:procedure Button4Click(Sender:

private{ Private declarations }

public{ Public declarations }

end;

var

TObject);TObject);TObject);TObject);

Page 33: Delphi учимся на примерах

32 Снимок экрана

Листинг 4.1. Продолжение

Forml: TForml; //главная формаВМР1: Graphics.TBitmap; //для работы с рисунками (*.bmp)DC1: HDC; //простое поле для графики

Imagel:. TImage;

implementation

{$R *.dfm}

procedure TForml.ButtonlClick(Sender: TObject);begin

Forml.Visible : = False; //прячем формуSleep(15);//пауза 15 мсBMP1 := Graphics.TBitmap.Create;//задаем размеры рисунка такие же как размеры экранаВМР1.Height := Screen.Height;ВМР1.Width := Screen.Width;DCl:=GetDC(O);//Делаем снимок экранаBitBlt(BMP1.Canvas.Handle,

Screen.Height, DC1,0, 0, Screen.Width,

0, 0, SRCCOPY);Forml.Visible := True; //восстанавливаем окно программыImagel := TImage.Create(nil) ;BMP1.IgnorePalette := True;Imagel.Picture.Assign(BMP1) ;BMP1.SaveToFile('с:\1.bmp'); //сохраняем снимок в файл

//l.bmp на диске С:\end;

procedure TForml.Button2Click(Sender: TObject);begin

if SaveDialogl.Execute thenBMP1.SaveToFile(SaveDialogl.FileName) //сохраняем рисунок

else ShowMessage('Файл не был сохранен!');end;

procedure TForml.Button3Click(Sender: TObject);begin

//удаляем рисунок с дискаif FileExists('с:M.bmp') then DeleteFile('С:\1.bmp');

Screenl.Hide; //скрываем рисунокend;

procedure TForml.Button4Click(Sender: TObject);begin

Page 34: Delphi учимся на примерах

Полный исходный код модуля 33

Листинг 4.1. Окончание

Screenl.Show; // делаем рисунок видимымif FileExists('с:\1.bmp') then //если рисунок существует,

Screenl.Picture.LoadFromFile('с:\1.bmp');//загружаем егоend;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 04.

3 — 5-1212

Page 35: Delphi учимся на примерах

34 Хранитель экрана

Глава 5

Хранитель экрана

Постановка задачиРазработать хранитель экрана для Windows (файл с расширением

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

Разработка формы

Создадим новый проект Delphi. Как известно, экранные заставкихранятся в файлах с расширением . scr, а по умолчанию проект Delphiкомпилируется как выполняемый файл . ехе. Для того чтобы наша про-грамма имела расширение . scr, выполним команду меню Project —> Op-tions, на вкладке Application диалогового окна Project Options введемв поле Target file extension значение scr (рис. 5.1) и нажмем кнопку ОК.

Все что нам понадобится на форме, — это два компонента Timerкатегории System. Первый будет служить для реализации постепенногонасыщения формы цветом — для этого таймера следует изменить зна-чение свойства I n t e r v a l на 100. Второй таймер потребуется при по-степенном уменьшении насыщенности цвета вплоть до того момента,когда форма вновь станет полностью прозрачной. Для этого таймерасвойству i n t e r v a l следует также присвоить значение 100, а значениесвойства Enabled изменить на False, поскольку изначально "затуха-ния" происходить не будет.

Page 36: Delphi учимся на примерах

Разработка формы 35

Project Options

Directories/Conditionals : Version Info PackagesForms Application Compiler j Linker

Application settings

litle: f

Help file: Г

[con: j ш^.

r̂owse...

Load Icon... j

' Output settings — "T arget file extension: I scr

Г JDefai! OK Cancel Help

Рис. 5.1. Выбор расширения для откомпилированной программы

Изменим свойства формы согласно табл. 5.1.

Таблица 5.1. Свойства формы хранителя экрана

Свойство

B o r d e r S t y l e

A l i g n

F o r r u S t y l e

A l p h a B l e n d

A l p h a B l e n d V a l u e

Значение

bsNone

a l C l i e n t

f s S t a y O n T o p

T r u e

1

Пояснение

Окно программы будет отображаться

без границы и заголовка

Окно программы будет заполнять весь

экран

Окно программы будет располагаться

поверх всех остальных окон

Разрешаем изменение степени про-

зрачности формы

Изначально окно программы полно-

стью непрозрачное

Page 37: Delphi учимся на примерах

36 Хранитель экрана

Разработка программного кодаОбъявите в разделе var переменную mouse типа TPoint. В этой

переменой будут храниться координаты указателя мыши, при измене-ниикоторых программа должна закрываться:

varForml: TForml;mouse: TPoint;

Программа экранной заставки должна закрываться не только подвижению мыши, но при любой активности пользователя. Для этогосоздадим обработчики некоторых событий главной формы. Созданиеформы (событие OnCreate):

procedure TForml.FormCreate(Sender: TObject);begin

GetCursorPos(mouse); //сохраняем координаты курсора мышиShowCursor(False); //прячем курсор

end;

Форма должна закрываться по нажатию любой клавиши (событиеOnKeyPress) и при движении мышью (событие OnMouseMove). Код об-работчика события OnKeyPress:procedure TForml.FormKeyPress(Sender: TObject; var Key:Char);begin

Halt; //завершение работы программыend;

Для события OnMouseMove программный код будет несколькоиным:procedure

beginif (X О

end;

TForml

mouse

.FormMouseMoveShift

(Sender: TObject;: TShiftState; X, Y:

.X) or (У О mouse.Y) then Halt;

Integer);

Здесь сначала выполняется проверка: были ли изменены координа-ты курсора. Если координаты курсора изменились, то, соответственно,мышь была сдвинута и следует закрыть программу.

Напишем собственную процедуру для выбора случайного цвета:color_check. Объявите ее как закрытый член класса формы:

Page 38: Delphi учимся на примерах

Разработка программного кода 37

typeTForml class(TForm)

private{ Private declarations }procedure color_check();

public{ Public declarations }

end;

В разделе implementation создадим реализацию процедурыcolor check:procedure TForml.colorvar

ran:

begin

check();

integer; //случайное число, соответствующее//определенному цвету

Randomize; //включаем генератор случайных чиселran := random(6) + 1 ; //выбираем случайное число от 1 до 6

//назначаем форме цвет, соответствующий выбранному числу

case1:2:

3:

4:

5:6:

end;

end;

ran ofForml.Color : =

Forml.Color :=

Forml.Color :=

Forml.Color :=

Forml.Color :=

Forml.Color :=

clBlack;

clWhite;clBlue;

clGray;

clYellow;

clGreen;

Здесь случайным образом выбирается число от 1 до 6, в зависимо-сти от того которого определяем цвет формы. Процедура c o l o r c h e c kбудет вызываться при каждом новом насыщении формы.

Обработчик события OnTimer первого таймера должен иметь сле-дующий вид:procedure TForml.TimerlTimer(Sender: TObject);begin

if Forml.AlphaBlendValue > 250then {проверяем: не полностью ли мы закрасили форму}begin

Timerl.Enabled := False; //выключаем насыщение формыTimer2.Enabled := True; //включаем обратный процесс

end;

//постепенное насыщение формыForml.AlphaBlendValue := Forml.AlphaBlendValue + 1;

end;

Page 39: Delphi учимся на примерах

38 Хранитель экрана

Насыщенность постепенно увеличивается на 1, и выполняется про-верка: не стала ли форма уже полностью закрашенной выбранным цве-том. Если нет, то продолжаем увеличивать насыщенность цвета черезкаждые 100 мс. Когда форма будет полностью насыщенной, начинаемобратный процесс, который будет происходить под управлением второ-го таймера (событие Time г 2 . OnTimer): ___procedure TForml.Timer2Timer(Sender: TObject);begin

if Forml.AlphaBlendValue < 5then //если форма уже полностью прозрачнаяbegin

color_check(); //выбираем случайный цвет для формыTimer2.Enabled := False; //выключаем второй таймерTimerl.Enabled := True; //включаем первый таймер

end;

//Уменьшаем прозрачность на 1Forml.AlphaBlendValue := Forml.AlphaBlendValue - 1;

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

Теперь программу можно откомпилировать, скопировать файл . scrв папку с хранителями экрана (для Windows ХР это папка Win-dows \System32), открыть окно параметров Рабочего стола и выбратьхранитель экрана, соответствующий нашей программе.

Разработанный нами хранитель экрана в действии показан нарис. 5.2. В данном случае был случайным образом выбран желтый цветзаполнения и происходит медленное насыщение этим цветом. Можноразглядеть папки, которые видны сквозь полупрозрачную форму.

Полный исходный код модуляПолный исходный код модуля программы Хранитель экрана пред-

ставлен в листинге 5.1.

Page 40: Delphi учимся на примерах

Полный исходный код модуля 39

Рис. 5.2. Хранитель экрана в действии

Листинг 5.1. Модуль программы Хранитель экрана

unit Unitl;

interface

uses

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

typeTForml = class(TForm)

Timerl: TTimer;Timer2: TTimer;procedure FormCreate(Sender: TObject);procedure FormKeyPress(Sender: TObject; var Key: Char);procedure FormMouseMove(Sender: TObject;

Shift: TShiftState; X, Y: Integer)procedure TimerlTimer(Sender: TObject);procedure Timer2Timer(Sender: TObject);

Page 41: Delphi учимся на примерах

40 Хранитель экрана

Листинг 5.1. Продолжение

private{ Private declarations }procedure color_check();

publicf Public declarations }

end;

varForml: TForml;mouse: TPoint;

implementation

{$R *.dfm)

procedure TForml.color_check(} ;var

ran: integer; //случайное число, соответствующее//определенному цвету

beginRandomize; //включаем генератор случайных чиселran : = Random(6) + 1; //выбираем случайное число от 1 до б//Назначаем форме цвет, соответствующий выбранному числуcase ran of

1: Forml.Color2: Forml.Color3: Forml.Color4: Forml.Color5: Forml.Color6: Forml.Color

clBlack;clWhite;clBlue;dGray;clYellow;clGreen;

end;end;

procedure TForml.FormCreate(Sender: TObject);begin

GetCursorPos(mouse); //получаем координаты курсора мышиShowCursor(False); //прячем курсор

end;

procedure TForml.FormKeyPress(Sender: TObject; var Key:Char)begin

Halt; //завершение работы программыend;

Page 42: Delphi учимся на примерах

Полный исходный код модуля 41

Листинг 5.1. Окончание

procedure TForml.FormMouseMove(Sender: TObject;Shift: TShiftState; X, Y: Integer);

beginif (X <> mouse.X) or (Y <> mouse.Y) then Halt;

end;

procedure TForml.TimerlTiraer(Sender: TObject);begin

if Forml.AlphaBlendValue > 250then //проверяем: не полностью ли мы закрасили формуbegin

TimerI.Enabled := False; //выключаем насыщение формыTimer2.Enabled := True; //включаем обратный процесс

end;//постепенное насыщение формыForml.AlphaBlendValue := Forml.AlphaBlendValue + 1;

end;

procedure TForml.Timer2Timer(Sender: TObject);begin

if Forml.AlphaBlendValue < 5then //если форма уже полностью прозрачнаяbegin

color_check(); //выбираем случайный цвет для формыTimer2.Enabled := False; //выключаем второй таймерTimerI.Enabled := True; //включаем первый таймер

end;

//Уменьшаем прозрачность на 1Forml.AlphaBlendValue := Forml.AlphaBlendValue - 1;

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 05.

Page 43: Delphi учимся на примерах

42 Программа просмотра рисунков

Глава 6

Программа просмотра рисунков

Постановка задачиРазработать программу для просмотра рисунков. Программа долж-

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

Разработка формыСоздайте новый проект Delphi. Разместите на форме компонент Im-

age категории Additional, который будет служить для отображения ри-сунка. Для того чтобы при любых размерах окна рисунок всегда запол-нял всю форму, следует изменить значение свойства Align на a l C l i -ent.

Для вызова диалоговых окон открытия и сохранения рисунка вос-пользуемся компонентами OpenDialog и SaveDialog категории Dia-logs. Присвоим свойству Name этих компонентов значения Openl иSavel соответственно. Для обоих компонентов присвойте свойствуF i l t e r значение Все файлы|*.*.

Для доступа к функциям программы будем использовать командыменю. Разместите на форме компонент MainMenu категории Standard.Для того чтобы создать пункты меню, следует дважды щелкнуть мы-шью на компоненте MainMenul, в результате чего откроется редакторменю, изображенный на рис. 6.1.

Для того чтобы добавить новый пункт, следует щелкнуть мышьюв этом окне на пустом элементе меню и изменить в инспекторе объектовзначение свойства Caption. Вначале создаются пункты меню, а затеманалогичным образом — подпункты (команды). Для создания раздели-телей свойству Caption следует присвоить значение - (дефис).

Page 44: Delphi учимся на примерах

Разработка формы 43

Irrl Forml.MainMenul

Рис. 6.1. Редактор меню

Создайте меню, соответствующее рис. 6.2.

Файл Правка

Открыть

Сохранить

Выход

Файл Правка ;

Очистить

Рис. 6.2. Меню для программы просмотра рисунков

Вид готовой формы представлен на рис. 6.3.

• : • • : _ _ : _ _ : • • ; • • : • ' : „ • • : • ' : _ : J

Рис. 6.3. Форма программы просмотра рисунков

Page 45: Delphi учимся на примерах

44 Программа просмотра рисунков

Разработка программного кодаТеперь создадим обработчики события OnClick для пунктов меню.

Для команды Файл -> Открыть: 'I procedure TForml.N2Click(Sender: TObject);begin

//начинаем обзор с текущей папкиOpenl.InitialDir := GetCurrentDir;//открываем диалоговое окно выбора файлаif Openl.Execute then begin

//загружаем выбранный рисунокImagel.Picture.LoadFromFile(Openl.FileName);Imagel.Show; //отображаем рисунок на форме

endelse //Если рисунок не был выбран

ShowMessage('Вы не выбрали рисунок!');Imagel.Show;

end;

Здесь мы просто открываем диалоговое окно выбора рисунка, и, ес-ли пользователь выбрал рисунок, то загружаем его в компонент Imagelи отображаем на форме.

procedure TForml.N3Click(Sender: TObject);begin

if Savel.Execute then //сохранение рисункаImagel.Picture.SaveToFile(Savel.FileName)

else ShowMessage('Рисунок не был сохранен!');

end;

Здесь мы открываем диалоговое окно сохранения рисунка, и, еслипользователь выбрал место сохранения файла, извлекаем этот путь(свойство Savel . FileName) и сохраняем отображаемый в данный мо-мент рисунок.

procedure TForml.N5Click(Sender: TObject);begin

Halt; //завершение работы программыend;

_ _ 9JEE!E2Ji!iISi5£^l!i Q" С Иск для пункта меню Правка —> Очистить:'"procedure TForml.N7Click(Sender: TObject);begin

Imagel.Hide; //прячем рисунокend;

Page 46: Delphi учимся на примерах

Разработка программного кода 45

Единственное, чего не достает этой программе, — это возможностьоткрывать с ее помощью рисунки в файл-менеджерах. Реализуем этувозможность, добавив следующий код в обработчик события OnCreateглавной фoJElJ!l!di___-_procedure TForml.FormCreate(Sender: TObject);var

Str:String; //путь к файлу, который поступил как параметрi:Integer;

beginif (ParamCount > 0)then //если на вход программы поступил параметрbegin

//составляем путь к файлу по символамStr := ParamStr(l);for i:=2 to ParamCount do

Str := Str + ' ' + ParamStr(i);

Imagel.Picture.LoadFromFile(str); //загружаем рисунокImagel.Show; //показываем рисунок

end;end;

При создании формы выполняется проверка: запускается ли про-грамма с параметрами. Если на вход поступили параметры, то опреде-ляем путь к рисунку и отображаем его на форме. Программа просмотрарисунков в действии представлена на рис. 6.4.

Рис. 6.4. Программа просмотра рисунков в действии

Page 47: Delphi учимся на примерах

46 Программа просмотра рисунков

Полный исходный код модуляПолный исходный код модуля программы просмотра рисунков

представлен в листинге 6.1.

Листинг 6.1. Модуль программы просмотра рисунков

ГипТГ Uniti;

i interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, Menus, ExtCtrls;

typeTForml = class(TForm)

Imagel: TImage;MainMenul: TMainMenu;N1: TMenuItem;N2: TMenuItem;N3: TMenuItem;N4: TMenuItem;N5: TMenuItem;N6: TMenuItem;N7: TMenuItem;Openl: TOpenDialog;Savel: TSaveDialog;procedure FormCreate(Sender: TObject);procedure N2Click(Sender: TObject);procedure N3Click(Sender: TObject);procedure N5Click(Sender: TObject);procedure N7Click(Sender: TObject);

private{ Private declarations }

public{ Public declarations }

end;

var

Forml: TForml;

implementation

{$R *.dfm}

Page 48: Delphi учимся на примерах

Полный исходный код модуля 47

Листинг 6.1. Продолжение

procedure TForml.FormCreate(Sender: TObject);var

Str: String; //путь к файлу, который поступил как параметрi:Integer;

beginif (ParamCount > 0)then //если на вход программы поступил параметрbegin

//составляем путь к файлу по символамStr := ParamStr(1);for i:=2 to ParamCount doStr := Str +'.*•+ ParamStr(i);

end;Imagel.Picture.LoadFromFile(str); //загружаем рисунокImage1.Show; //показываем рисунок

end;end;

procedure TForml.N2Click(Sender: TObject);begin

//начинаем обзор с текущей папкиOpenl.InitialDir := GetCurrentDir ;//открываем диалоговое окно выбора файлаif Openl.Execute thenbegin

//загружаем выбранный рисунокImagel.Picture.LoadFromFile(Openl.FileName);Imagel.Show; //показываем рисунок на форме

endelse //Если рисунок не был выбран

ShowMessage('Вы не выбрали рисунок!');Imagel.Show;

end;

procedure TForml.N3Click(Sender: TObject);begin

if Savel.Execute then //сохранение- рисункаImagel.Picture.SaveToFile(Savel.FileName)

else ShowMessage('Рисунок не был сохранен!');end;

procedure TForml.N5Click(Sender: TObject);begin

Halt; //выход из программы

I end;

_ _ _ _ _ _ _

Page 49: Delphi учимся на примерах

48 Программа просмотра рисунков

Листинг 6.1. Окончание

L

procedure TForml.N7Click(Sender: TObject);begin

Image1.Hide; //прячем рисунокend;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ 0 6.

Page 50: Delphi учимся на примерах

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

Глава 7

Блокнот-шифровальщик

Постановка задачиРазработать программу, повторяющую функции стандартного

блокнота с дополнительной возможностью шифрования и дешифрова-ния данных.

Разработка формыСоздадим новый проект Delphi. Интерфейс программы сделаем по-

хожим на интерфейс стандартного блокнота. Разместите на форме ком-понент Memo (многострочное текстовое поле) категории Standard. Длятого чтобы при любых размерах окна этот компонент заполнял всюформу, измените значение свойства Memol.Al-ign на a l C l i e n t . Длятекстового поля должна отображаться только вертикальная полоса про-крутки (то есть, будет выполняться автоматический перенос слов но но-вую строку). Для этого следует изменить значение свойства S c r o l l -Bars на s s V e r t i c a l .

Разместите на форме компонент MainMenu категории Standard исоздайте меню, представленное на рис. 7.1.

Файл Правка Формат |

Открыть

Сохранить

Закрыть

ншавш;Файл Правка Формат ;...,..

Число XOR

Зашифровать/РасшифроватОчистить

Файл Праака Формат

*/ Перенос по словам

Шрифт

Рис. 7.1. Меню программы Блокнот-шифровальщик

Разработка меню рассматривается в предыдущей главе.

Для пункта меню Формат —> Перенос по словам следует установитьсвойство Checked равным True, поскольку этот пункт меню будет вы-полнять роль переключателя.

4 — 5-1212

Page 51: Delphi учимся на примерах

50 Блокнот-шифровальщик

Для вызова диалогового окна открытия файла будем использоватькомпонент OpenDialog категории Dialogs, а для сохранения файла —компонент SaveDialog той же категории. Для обоих компонентов из-мените значение свойства F i l t e r на Блокнот | * . t x t | Все файлы | * . *.Также разместите на форме еще один компонент категории Dialogs:Font Dialog. Он будет служить для изменения шрифта.

Больше ничего добавлять на форму не нужно, и результат оформле-ния должен соответствовать рис. 7.2.

Рис. 7.2. Форма блокнота-шифровальщика

Разработка программного кодаШифровать текст будем с помощью функции хог или обычного

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

Прежде всего объявите глобальную переменную xr_num типаstring:

varForml: TForml;xr_num: s tring;

Page 52: Delphi учимся на примерах

Разработка программного кода 51

Теперь займемся командами меню. Обработчик события OnClickдля пункта Файл —> Открыть:procedure TForml.NIClick(Sender: TObject);begin

//начинаем обзор с текущей папкиOpenDialogl.InitialDir := GetCurrentDir;if not OpenDialogl.Executethen ShowMessage('File not selected!')else //загружаем выбранный файл в MemoMemol.Lines.LoadFromFile(OpenDialogl.FileName);

end;

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

Обработчик события OnClick для пункта Файл —> Сохранить:procedure TForml.N2Click(Sender: TObject);begin

Savedialogl.InitialDir := GetCurrentDir;if not SaveDialogl.Executethen ShowMessage('File not saved!

1)

else //сохраняем в файл

Memol.Lines.SaveToFile(SaveDialogl.FileName);

end;

Открываем диалоговое окно сохранения файла. После того какпользователь выбрал место сохранения файла, извлекаем текст из Memoи сохраняем его в выбранной папке.

Обработчик события OnClick для пункта Файл —> Выход:procedure TForml.N4Click(Sender: TObject);begin

Close; //закрыть программуend;

Обработчик события OnClick для пункта Правка -> Число XOR:procedure TForml.XoRlClick(Sender: TObject);begin

if not InputQuery('XOR', 'Введите число xor:', xr_num)

then Exit;

end;

Здесь мы отображает окно для выбора числа хог. Указанное пользо-вателем число будет занесено в переменную xr_num.

Обработчик события OnClick для пункта Правка -» Зашифро-вать/Расшифровать:

4*

Page 53: Delphi учимся на примерах

52 Блокнот-шифровальщик

[procedure TForml.N5Click(Sender: TObject);j var

xr: string; //зашифрованный текстi: integer; //счетчик цикла

1 beginfor i:=1 to Length(Memol.Text) dobegin //перебираем каждый символ в тексте

//выполняем указанное пользователем смещениеxr := xr + Chr(Ord(Memol.Text[i]) xor StrToInt(xr_num));

end;

//заменяем оригинальный текст на зашифрованныйMemol.Text := xr;

end;

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

Обработчик события OnClick для пункта Правка —* Очистить:procedure TForml.N8Click(Sender: TObject);begin

Memol.lines.Clear; //очистка Memo

end;

Очищаем поле Memo от содержащегося в нем текста.Обработчик события OnClick для пункта Формат -» Перенос по

словам: _____[procedure TForml.N9Click(Sender: TObject);

begini f N9.Checked then //если флажок установленbegin• N9.Checked := False; //сбрасываем флажок

//Отображаем горизонтальную полосу прокруткиMemol.ScrollBars := ssBoth;

endelse begin //если флажок не установлен

N9.Checked := True; //устанавливаем флажок//убираем горизонтальную полосу прокруткиMemol.ScrollBars := ssVertical;

end;end;

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

Page 54: Delphi учимся на примерах

Разработка программного кода 53

procedure TForml.NIOClick(Sender: TObject);begin

//Определяем все настройки шрифта и отображаем их//в диалоговом окнеFontDialogl.Font.Color := Memol.Font.Color; //цвет шрифтаFontDialogl.Font.Style := Memol.Font.Style; //стильFontDialogl.Font.Size := Memol.Font.Size; //размерFontDialogl.Font.Charset := Memol.Font.Charset; //кодировкаFontDialogl.Font.Name := Memol.Font.Name; //название шрифтаif FontDialogl.Execute thenbegin //применяем все выбранные настройкиMemol.Font.Color := FontDialogl.Font.Color;Memol.Font.Style := FontDialogl.Font.Style;Memol.Font.Size := FontDialogl.Font.Size;

Memol.Font.Charset := FontDialogl.Font.Charset;:Memol.Font.Name := FontDialogl.Font.Name;

end;end;

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

Теперь осталось только реализовать автоматическую загрузку фай-лов, связанных с нашим блокнотом в файл-менеджерах. Для этого соз-дадим обработчик события OnCreate главной формы:procedure TForml.FormCreate(Sender: TObject);var

Str: String; //путь к параметруi: Integer;

beginxr num := '2'; //по умолчанию смещение « 2if (ParamCount > 0) thenbegin

Str := ParamStr(l);//Формируем путь к аргументуfor i:=2 to ParamCount do Str := Str +•__*.+ ParamStr(i) ;

end;{Если на вход программы поступили параметры, то отображаем

содержимое соответствующего файла в поле Memo }if Str О " then Memol.Lines.LoadFromFile(str);

end;

Здесь мы задаем начальное значение для смещения и проверяем,поступили ли на вход программы какие-либо параметры. Если да, то уз-

Page 55: Delphi учимся на примерах

54 Блокнот-шифровальщик

наем путь к файлу и отображаем его содержимое в поле Memo. Примершифрования со смещением 10 представлен на рис. 7.3.

Файл Правка Формат

* (Длъкньдисг*еъвлдъЬ*исед6зхфувг*едипъащ*оъ1цйдйд*е1ьЕл [

дък*одбмпэ*лсшц*ед*аъкгэпг*жпъп*эк*шъв*абкыык*шдээдыш

вС

Рис. 7.3. Пример шифрования со смещением 10

Полный исходный код модуляПолный исходный код модуля программы Блокнот-шифровальщик

представлен в листинге 7.1.

Листинг 7.1. Модуль программы Блокнот-шифровальщик

unit Unitl

interface

uses

Windows,

Controls

typeTForml =

Memol:

menul:

Filel:

Editl:

Messages, SysUtils, Variants, Classes, Graphics,

Forms, Dialogs, StdCtrls, Menus;

class(TForm)TMemo;

TMainMenu;TMenuItem;TMenuItem;

N1: TMenuItem;N2: TMenuItem;

N3: TMenuItem;

Page 56: Delphi учимся на примерах

Полный исходный код модуля 55

Листинг 7.1. Продолжение

N4: TMenuItem;N5: TMenuItem;N7: TMenuItem;N8: TMenuItem;OpenDialogl: TOpenDialog;SaveDialogl: TSaveDialog;FontDialogl: TFontDialog;N6: TMenuItem;N9: TMenuItem;N10: TMenuItem;XoRl: TMenuItem;procedure NIClick(Sender: TObject);procedure N2Click(Sender: TObject);procedure N4Click(Sender: TObject);procedure N8Click(Sender: TObject);procedure N5Click(Sender: TObject);procedure N9Click(Sender: TObject);procedure NIOClick(Sender: TObject);procedure FormCreate(Sender: TObject);procedure XoRlClick(Sender: TObject);

private{ Private declarations }

public

{ Public declarations }end;

var

Forml: TForml;xr_num: string;

implementation($R *.dfm)

procedure TForml.NIClick(Sender : TObject);beginOpenDialogl.InitialDir := GetCurrentDir;if not OpenDialogl.Executethen ShowMessage('File not selected!')else //загружаем выбранный файл в Memo

Memol.Lines.LoadFromFile(OpenDialogl.FileName);end;

procedure TForml.N2Click(Sender: TObject);begin

SaveDialogl.InitialDir := GetCurrentDir;

Page 57: Delphi учимся на примерах

56 Блокнот-шифровальщик

Листинг 7.1. Продолжение

if not SaveDialogl.Executethen ShowMessage('File not saved!')else //сохраняем в файлMemol.Lines.SaveToFile(SaveDialogl.FileName);

end;

procedure TForml.N4Click(Sender: TObject);begin

Close; //выход из программыend;

procedure TForml.N8Click(Sender: TObject);begin

Memol.lines.Clear; //очищаем Memoend;

procedure TForml.N5Click(Sender: TObject);var

xr: string; //зашифрованный текстi: integer; //счетчик цикла

beginfor i:=l to Length(Memol.Text) dobegin //перебираем каждый символ в тексте

//Выполняем указанное пользователем смещениеxr := xr + Chr(Ord(Memol.Text[i]) xor StrToInt(xr_num)

end;//заменяем оригинальный текст на зашифрованныйMemol.Text := xr;

end;

procedure TForml.N9Click(Sender: TObject);begin

if N9.Checked then //если флажок установленbeginN9.Checked := False; //сбрасываем флажок//Отображаем горизонтальную полосу прокруткиMemol.ScrollBars := ssBoth;

endelse begin //если флажок не установлен

N9.Checked := True; //устанавливаем флажок//убираем горизонтальную полосу прокруткиMemol.ScrollBars := ssVertical;

end;end;

Page 58: Delphi учимся на примерах

Полный исходный код модуля 57

Листинг 7.1. Продолжение

procedure TForml.NIOClick(Sender: TObject);begin

//Определяем все настройки шрифта и отображаем их в окнеFontDialogl.Font.Color := Memol.Font.Color; //цвет шрифтаFontDialogl.Font.Style : = Memol.Font.Style; //стильFontDialogl.Font.Size := Memol.Font.Size; //размерFontDialogl.Font.Charset : = Memol.Font.Charset; //кодировкаFontDialogl.Font.Name := Memol.Font.Name; //название шрифтаif FontDialogl.Execute then begin

//применяем все выбранные настройкиMemol.Font.Color : = FontDialogl.Font.Color;Memol.Font.Style := FontDialogl.Font.Style;Memol.Font.Size := FontDialogl.Font.Size;Memol.Font.Charset := FontDialogl.Font.Charset;Memol.Font.Name : = FontDialogl.Font.Name;

endend;

procedure TForml.FormCreate(Sender: TObject);

var

Str:String; //путь к параметруi:Integer;

beginxr_num := '2'; //по умолчанию смещение = 2if (ParamCount > 0) thenbegin

Str := ParamStr(1);//Формируем путь к параметруfor i:=2 to ParamCount do Str := Str + ' ' + ParamStr(i);

end;

{Если на вход программы поступили параметры, то отображаемсодержимое соответствующего файла в поле Memo }if str о " then Memol.Lines.LoadFromFile(str);

end;

procedure TForml.XoRlClick(Sender: TObject);begin

if not InputQuery('XOR', 'Введите число xor:', xr_num)then exit;

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ 0 7 .

Page 59: Delphi учимся на примерах

58 Игра "Успей щелкнуть"

Глава 8

Игра "Успей щелкнуть"

Постановка задачиПо всему экрану мелькает форма, и цель игры — успеть щелкнуть

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

Разработка формыСоздадим новый проект Delphi. Мелькающее окно у нас будет не-

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

Таблица 8.1. Свойства формы игры "Успей щелкнуть"

Свойство

B o r d e r S t y l e

F o r m S t y l e

C o l o r

H e i g h t

W i d t h

Значение

bsNone

f s S t a y O n T o p

c l W i n d o w T e x t

72

208

Пояснение

Окно программы будет отображаться без

границы и заголовка

Окно программы должно располагаться

поверх всех остальных окон, поскольку

игрок не всегда будет "попадать" по на-

шему окну, а значит своими "промахами"

будет активизировать другие окна

Цвет формы — черный

Высота

Ширина

Разместитете его свойства

на форме компонент Label категории Standard. Измени-согласно табл. 8.2.

Таблица 8.2. Свойства первого компонента L a b e l

Свойство

C a p t i o n

F o n t . C o l o r

Значение

П о п а д а н и я :

c l L i m e

Пояснение

Надпись метки

Цвет шрифта — светло-зеленый

Page 60: Delphi учимся на примерах

Разработка формы 59

Таблица 8.2. Окончание

Свойство

Font.Name

Font.S ize

F o n t . S t y l e

L e f t

Top

Значение ,

C o u r i e r New

12

[ f s B o l d ]

16

16

Пояснение

Название шрифта

Размер шрифта

Начертание шрифта — полужирное

Отступ слева

Отступ сверху

Разместите на форме еще один компонент Label и измените егосвойства согласно табл. 8.3.

Таблица 8.3. Свойства второго компонента L a b e l

Свойство

Name

C a p t i o n

F o n t . C o l o r

Font.Name

F o n t . S i z e

F o n t . S t y l e

L e f t

Top

Значение

p o p a d

0

c l R e d

C o u r i e r New

16

[ f s B o l d ]

120

16

Пояснение

Новое имя компонента

Надпись метки

Цвет шрифта — красный

Название шрифта

Размер шрифта

Начертание шрифта — полужирное

Отступ слева

Отступ сверху

Разместите на форме третий компонент Label, который будет ото-бражать предельное число "попаданий", и измените его свойства со-гласно табл. 8.4.

Таблица 8.4. Свойства третьего компонента L a b e l

Свойство

C a p t i o n

F o n t . C o l o r

Font.Name

F o n t . S i z e

F o n t . S t y l e

L e f t

Top

Значение

/ 1 0

c l R e d

C o u r i e r New

16

[ f s B o l d ]

144

16

Пояснение

Надпись метки

Цвет шрифта — красный

Название шрифта

Размер шрифта

Начертание шрифта — полужирное

Отступ слева

Отступ сверху

Напоследок разместите на форме компонент Timer категории Sys-tem. Результат оформления формы должен соответствовать рис. 8.1.

Page 61: Delphi учимся на примерах

60 Игра "Успей щелкнуть"

Рис. 8.1. Форма для игры "Успей щелкнуть"

Разработка программного кодаИзменение формы окна на эллиптическую реализуется в обработ-

чике события OnCreate формы. Для этого необходимо объявить гло-бальную переменную forma типа HRGN, которая будет содержать разме-ры окна:

varForml: TForml;forma: HRGN;

В обработчик события OnCreate добавьте следующий код:procedure TForml.FormCreate(Sender:begin

Randomize; //включаем генераторforma := CreateEllipticRgn(0, 0,

Forml.//применяем новый вид окнаSetWindowRgn(Handle, forma, True)

end;

TObject)

случайных

" "1

чиселForml.Width,

Height);

;

//вид окна

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

координаты в пределах экрана. Это будет реализовано в обработчикесобытия Timer 1. OnTimer:procedure TForml.TimerlTimer(Sender: TObject);

beginForml.Top := Random(Screen.Height) + 1; //случайная высотаForml.Left := Random(Screen.Width) + 1; //случайная ширина

end;

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

Теперь выделите все компоненты и саму форму и создайте для нихобщий обработчик события OnMouseDown:procedure TForml.popadMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

Page 62: Delphi учимся на примерах

Разработка программного кода 61

beginif StrToInt(popad.Caption) < 10 thenbegin //если попаданий меньше 10

//Перемещаем окно в случайную позицию по вертикалиForml.Top := Random(Screen.Height) + 1;//Изменяем положение по горизонталиForml.Left := Random(Screen.Width) + 1;//Увеличиваем счетчик "попаданий" на единицуpopad.Caption := IntToStr(StrToInt(popad.Caption) + 1) ;//Увеличиваем скорость перемещения окна на 100 мсTimerl.Interval := Timerl.Interval - 100;

end;

if popad.Caption = 40' thenbegin //если игрок попал 10 раз

Timerl.Enabled := False; //останавливаем игруForml.Position := poDesktopCenter; //окно- в центр экрана//сообщаем о победеShowMessage('Вы попали по окну 10 раз!');if Application.MessageBox('Игра', 'Играть еще раз?',

mb_yesno + mb taskmodal +mb_iconQuestion) = idYes

then {предлагаем сыграть еще раз}begin

popad.Caption := 'О1; //сброс результатов

//Придаем окну эллиптическую формуforma := CreateEllipticRgn(0, 0,

Forml.Width, Forml.Height);SetWindowRgn(Handle, forma, True);

//Устанавливаем начальную скорость перемещения окнаTimerl.Interval := 1000;Timerl.Enabled := True; //начинаем игру-

end

else Halt; //выход из игрыend;

end;

При .каждом "попадании" выполняется проверка: было ли это "по-падание" последним. Если да, то просто пополняем счетчик попаданийи увеличиваем скорость перемещения формы на 100 мс. Если игрок сде-лал последнее "попадание", то останавливаем игру, выводим окно вцентр экрана и показываем сообщение о том, что игра успешно оконче-на. После этого отображаем окно с вопросом: следует ли начинать игрузаново. Если пользователь отказывается играть, то просто выходим изпрограммы. Если пользователь хочет сыграть сначала, то обнуляем всерезультаты и начинаем игру заново.

Page 63: Delphi учимся на примерах

62 Игра "Успей щелкнуть"

Окно программы в процессе игры представлено на рис. 8.2.

Рис. 8.2. Игра "Успей щелкнуть" в действии

Полный исходный код модуляПолный исходный код программного модуля игры "Успей щелк-

нуть" представлен в листинге 8.1.

Листинг 8.1. Программный модуль игры "Успей щелкнуть"

unit Unitl;

interface

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

typeTForml = class(TForm)

Label2: TLabel;popad: TLabel;Label3: TLabel;Timerl: TTimer;procedure FormCreate(Sender: TObject);procedure TimerITimer(Sender: TObject);procedure popadMouseDown(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer)

private( Private declarations }

public{ Public declarations }

end;

varForml: TForml;forma: HRGN;

implementation

{$R *.dfm}

Page 64: Delphi учимся на примерах

Полный исходный код модуля 63

Листинг 8.1. Продолжение

procedure TForml.FormCreate(Sender: TObject);begin

Randomize; //включаем генератор случайных чиселforma := CreateEllipticRgn(0, 0, Forml.Width,

Forml.Height);//форма окна

//применяем новый вид окнаSetWindowRgn(Handle, forma, True);

end;

procedure TForml.TimerITimer(Sender: TObject);begin

forml.Top := Random(Screen.Height) + 1; //случайная высотаforml.Left := Random(Screen.Width) + 1; //случайная ширина

end;

procedure TForml.popadMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);begin

if StrToInt(popad.Caption) < 10 thenbegin //если попаданий меньше 10

//Перемещаем окно в случайную позицию по вертикалиForml.Top := Random(Screen.Height) + 1;//Изменяем положение по горизонталиForml.Left : = Random(Screen.Width) + 1;//Увеличиваем счетчик "попаданий" на единицуpopad.Caption := IntToStr(StrToInt(popad.Caption) + 1);//Увеличиваем скорость перемещения окна на 100 мсTimerI.Interval := Timerl.Interval - 100;

end;

if popad.Caption = '10' thenbegin //если игрок попал 10 раз

Timerl.Enabled := False; //останавливаем игруForml.Position := poDesktopCenter; //окно- в центр экрана//сообщаем о победе

ShowMessage('Вы попали по окну 10 раз!');if Application.MessageBox('Игра', 'Играть еще раз?',

mb_yesno + mb_taskmodal +mb_iconQuestion) = idYes

then {предлагаем сыграть еще раз}begin

popad.Caption := '0'; //сброс результатов//Придаем окну эллиптическую формуforma := CreateEllipticRgn(0, 0,

Forml.Width, Forml.Height);SetWindowRgn(Handle, forma, True);//Устанавливаем начальную скорость перемещения окна

Page 65: Delphi учимся на примерах

64 Игра "Успей щелкнуть"

•. • • . • . - ; . . : • • • • . • : , • • . .

Листинг 8.1. ОкончаниеTimerl

Timerl

end

Interval :

Enabled : =

else Halt; //выход

end;

end;

end.

- 1000;

True; //начинаем игру

из игры

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 08.

Page 66: Delphi учимся на примерах

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

Глава 9

"Угадывание чисел"

Постановка задачиРазработать игру, цель которой заключается в угадывании случай-

ного числа из заданного диапазона чисел. Дать возможность играть ссоперником или против компьютера.

Разработка формыСоздайте новый проект Delphi и присвойте свойству Caption (за-

головок) формы значение Игра. Угадывание чисел. Вверху формыбудут расположены элементы управления для настройки диапазона уга-дываемых чисел. Разместим на форме три компонента Label (метки)категории Standard и два компонента Edit (поле ввода) той же катего-рии. Изменим их свойства согласно табл. 9.1.

Таблица 9.1. Свойства компонентов для настройки диапазона угадываемых чисел

Компонент

L a b e l l

Label2

Label3

Свойство

Caption

Font.Style

L e f t

Top

Capt ion

F o n t . S t y l e

L e f t

Top

Capt ion

F o n t . S t y l e

L e f t

Top

Значение

Диапазон чисел:

[ f s B o l d ]

8

16

от

[ f s B o l d ]

104

16

до

[ f s B o l d ]

216

16

Пояснение

Надпись метки

Начертание шрифта —

полужирное

Отступ слева

Отступ сверху

Надпись метки

Начертание шрифта —

полужирное

Отступ слева

Отступ сверху

Надпись метки

Начертание шрифта —полужирное

Отступ слева

Отступ сверху

5 — 5-1212

Page 67: Delphi учимся на примерах

66 Игра "Угадывание чисел"

Таблица 9.1. Окончание

Компонент

E d i t l

E d i t 2

Свойство

Name

T e x t

L e f t

Top

W i d t h

Name

T e x t

L e f t

Top

W i d t h

Значение

s t a r t

1

128

8

57

f i n i s h

1000

256

8

57

Пояснение

Новое имя поля, предназначенного для

ввода начального числа диапазона

Содержимое поля

Отступ слева

Отступ сверху

Ширина

Новое имя поля, предназначенного для

ввода конечного числа диапазона

Содержимое поля

Отступ слева

Отступ сверху

Ширина

Разместите на форме под этими компонентами еще один компонентLabel, назовите его p l l (свойство Name), а свойству Caption присвой-те значение Первый игрок:. Справа от метки pi 1 разместите компонентEdit, свойству Name которого присвойте значение chl , а свойствуT e x t — значение 0. Справа от поля chl разместите еще один компо-нент Label. Присвойте ему имя znakl и очистите свойство Caption.

Под компонентами p l l , chl и znakl разместите аналогичные ком-поненты для второго игрока, присвоив им имена р12, ch2 и znak2 со-ответственно. Свойству р12 .Caption присвойте значение Второй иг-рок:, свойству ch2.Text — значение 0, а свойство znak2 .Captionочистите. Поскольку по умолчанию игру будет начинать первый игрок,мы должны заблокировать ввод для второго игрока. Для этого изменитезначение свойства Enabled для компонентов сп2 и р12 на False.

Разместите на форме справа от компонентов znakl и znak2 ещеодин компонент Label и измените его свойства согласно табл. 9.2.

Таблица 9.2. Свойства нового компонента L a b e l

Свойство

Name

C a p t i o n

F o n t . C o l o r

Font.Name

F o n t . S i z e

Значение

X

X

c l R e d

C o u r i e r New

36

Пояснение

Новое имя компонента

Надпись метки

Цвет шрифта — красный

Название шрифта

Размер шрифта

Page 68: Delphi учимся на примерах

Разработка программного кода 67

Таблица 9.2. Окончание

Свойство

F o n t . S t y l e

H e i g h t

Значение

[ f s B o l d ]

54

Пояснение

Начертание шрифта — полужирное

Высота метки

Ниже всех компонентов разместите компонент Checkbox (флажок)категории Standard. Присвойте его свойству Name значение comp, aсвойству Caption — значение Играть против компьютера (просле-дите также, чтобы свойство Checked было равно False).

Ниже разместите две кнопки (компонент Button категории Stan-dard), присвоив их свойству Caption значения Принять вариант иНовая игра. Полученная форма должна соответствовать рис. 9.1.

Ш Игра. Угадывание чисел

Днпазон чисел: от

Первый игрок: \"

до1000

| Играть против компьютера

; ; ; Принять вариант 1;

X

Новая игра

Рис. 9.1. Форма для игры "Угадывание чисел"

Разработка программного кодаПрежде всего, объявим переменные, которые будем использовать

varForml: TForml;num, j, i, kolvo, big, small: integer;maximum, minimum: array [1..100] of integer; {массивы

максимальных и минимальных чисел}

Переменная num соответствует случайно заданное число, перемен-ной kolvo — количество попыток, за которые число было отгадано, пе-ременной b i g — наибольшее число из названных, а переменнойsmall — наименьшее число из названных.

Page 69: Delphi учимся на примерах

68 Игра "Угадывание чисел"

Теперь напишем две процедуры, которые в случае игры противкомпьютера будут определять границы нахождения числа. Процедураmin будет определять нижнюю границу, а процедура max — верхнюю.Объявим эти процедуры как закрытые члены класса формы:type

TForml - class(TForm)

private{ Privateprocedure

procedure

public( Public с

end;

declarations )min () ;max () ;

ieclarations }

После этого создадим сами процедуры в разделе implementation://процедура нахождения наименьшего числаprocedure TForml.min();

begin

for i: =1 to kolvo do begin

for j:=1 to kolvo do begin

(Если число меньше наименьшего,то оно становится наименьшим}if minimum[j] > small then small := minimum[j];

end;

end;

end;

//процедура нахождения наибольшего числа «procedure Tforml.max();var temp: integer;begin

temp := StrTolnt(finish.Text);for i:=1 to kolvo do begin

for j:=1 to kolvo do beginif temp > maximum[j] then

if maximumtj] > 0 then temp:=maximum[j]; (если число

больше наибольшего...}end;

end;if ( (temp <> 0) and (temp <> StrTolnt(finish.Text)) ) then

{... и если число входит в допустимый диапазон,то оно становится наибольшим}

big := temp;end;

Page 70: Delphi учимся на примерах

Разработка программного кода 69

Рассмотрим процедуру, которая будет выполняться при созданииформы:procedure TForml.FormCreate(Sender: TObject);beginRandomize; //включаем генератор случайных чисел//загадываем случайное число из заданного диапазонаnum := Random(StrToInt(finish.Text) -

StrToInt(start.Text)) + StrToInt(start.Text);kolvo := 0; //обнуляем количество попытокbig := StrToInt(finish.Text); //самое большое числоsmall := StrToInt(start.Text); //самое маленькое число

end;

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

Самое главное событие — нажатие кнопки Принять вариант. Созда-дим для этого кнопки обработчик события OnClick:procedure TForml.Button2Click(Sender: TObject);begin

//увеличиваем количество попыток на единицуkolvo := kolvo + 1;if not сотр.Checked then //если идет игра с человекомbegin

if pll.Enabled then begin //если ход первого игрока//если вариант больше загаданного числа, ставим знак >if StrToInt(chl.Text) > num then znakl.Caption := '>';//если вариант меньше загаданного числа, ставим знак <if StrToInt(chl.Text) < nun then znakl.Caption :• '<';if StrToInt(chl.Text) • num then //если число угаданоbegin

znakl.Caption := '='; //изменим знак на "="//вместо знака "X" показываем загаданное числох.Caption := IntToStr(num);//выводим сообщение о победе первого игрокаShowMessage('Победил первый игрок!' + #13#10 +

'Число угадано эа ' + IntToStr(kolvo) +' попытки')

end;

//передаем ход второму игрокуpll.Enabled := False;chl.Enabled := False;ch2.Enabled := True;pl2.Enabled := True;Exit; //прерываем выполнение процедуры

Page 71: Delphi учимся на примерах

70 Игра "Угадывание чисел"

end;if pl2.Enabled then begin //если ход второго игрока

{сравниваем загаданное число с вариантом второгоигрока и ставим соответствующий знак}if StrToInt(ch2.Text) > пшп then znak2.Caption := '>';if StrToInt(ch2.Text) < num then znak2.Caption := '<';if StrToInt(ch2.Text) = num thenbegin

znak2.Caption := ' =' ;

x.Caption := IntToStr(num);ShowMessage('Победил второй игрок!

1 + #13#10 +

'Число угадано За ' + IntToStr(kolvo) +1 попытки')

end;end;

//передаем ход первому игрокур12.Enabled := False;ch2.Enabled := False;chl.Enabled := True;pll.Enabled := True;Exp-

end;

if comp.Checked then begin //если игра против компьютера{проверяем вариант первого игрока и ставимсоответствующий знак}

if StrToInt(chl.Text) > num then znakl.Caption := '>';if StrToInt(chl.Text) < num then znakl.Caption := '<';if StrToInt(chl.Text) = num thenbegin

znakl.Caption := '=';

x.Caption := IntToStr(num);

ShowMessage('Вы победили!' + #13#10 +

'Число угадано за ' + IntToStr(kolvo) +' попытки');

Exit;end;

//если вариант первого игрока больше загаданного числа}if znakl.Caption = '>' thenbegin

maximum[kolvo] := StrToInt(chl.Text); {добавляемв массив наибольших чисел вариант первого игрока}

max(); //ищем наибольшее числоend;

//если вариант первого игрока меньше загаданного числа)if znakl.Caption = '<' then beginminimum[kolvo] := StrToInt(chl.Text); {добавляем число

в массив наименьших чисел, выданных первым игроком}

Page 72: Delphi учимся на примерах

Разработка программного кода 71

min(); //ищем наименьшее числоend;

//после всех расчетов, компьютер выдает свой вариантch2.Text := IntToStr(Random(big - small) + small);

end;

//проверяем вариант компьютера и ставим соответствующий зьif StrToInt(ch2.Text) > num then znak2.Caption := '>';if StrToInt(ch2.Text) < num then znak2.Caption := '<';if StrToInt(ch2.Text) = num then begin

znak2.Caption := '=';x.Caption := IntToStr(num);ShowMessage('Вы проиграли!' + #13#10 +

'В этот раз победил компьютер!' + #13#10 +'Число угадано за ' + IntToStr(kolvo) +1 попытки');

end;end;

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

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

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

Если текущий вариант игрока меньше загаданного числа, то мы до-бавляем его в массив наименьших чисел. В этом массиве ищется самоебольшое число среди наименьших. Тем самым мы постоянно сокращаем

Page 73: Delphi учимся на примерах

72 Игра "Угадывание чисел"

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

Для того чтобы можно было переключаться между режимами игры"с человеком" и "против компьютера", создадим обработчик событияOnclick для флажка сошр:procedure TForml.compClick(Sender: TObject);begin

if comp.Checked then begin //если флажок установлен//блокируем ввод от второго игрокаch2.Enabled := False;

р12.Enabled := False;

//включаем ввод от первого игрокаchl.Enabled := True;pll.Enabled := Truer-

endelse begin

//если игра идет с человеком, то//включаем ввод для второго игрокаch2.Enabled := True;р12.Enabled := True;

ивЛ;end;

procedure TForml.ButtonlClick(Sender: TObject);begin

if ((StrToInt(finish.Text) > StrToInt(start.Text)) and(StrToInt(start.Text) > 0) and(StrToInt(finish.Text) < 60000))

then (проверяем, не выходит ли заданное пользователем числоза допустимые пределы }

{загадаем случайное число в заданном диапазоне}num := Random(StrToInt(finish.Text) -

StrToInt(start.Text)) +StrToInt(start.Text)

else ShowMessage('Неверный диапазон!');//обнуляем все, и придаем программе начальный видznakl.Caption := '•; _znak2 . Caption : •= ' ' ;chl.Enabled :• True;ch2.Enabled := False;pll.Enabled := True;pl2.Enabled := False;x.Caption :« 'X';chl.Text :•» '0';ch2.Text := '0';

Page 74: Delphi учимся на примерах

Полный исходный код модуля 73

I

//очистим массивы наибольших и наименьших чиселfor i:=1 to kolvo+1 dobeginminimum[i] := 0;maximum[i] := 0;

big := StrToInt(finish.Text); //наибольшее числоsmall := StrToInt(start.Text); //наименьшее число

end;

kolvo := 0; //количество использованных попытокend;

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

Компилируем и запускаем программу на выполнение. Играв действии показана на рис. 9.2.

[игра. Угадывание чисел

Дкпазон чисел: от 300

Первый игрок: ]320

Второй игрок: |303 v »

jv Играть против компьютера

|Принять вариант!

до Р ^ —

320

Новая игра

Рис. 9.2. Игра "Угадывание чисел" в действии

Полный исходный код модуляПолный исходный код программного модуля игры "Угадывание чи-

сел" представлен в листинге 9.1.

Page 75: Delphi учимся на примерах

74 Игра "Угадывание чисел"

Листинг 9.1. Программный модуль игры "Угадывание чисел"

| unit Unitl;

interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms,Dialogs, StdCtrls, ExtCtrls;

typeTForml = class(TForm)

Buttonl: TButton;Labell: TLabel;Label2: TLabel;start: TEdit;finish: TEdit;Label3: TLabel;pll: TLabel;chl: TEdit;pl2: TLabel;ch2: TEdit;comp: TCheckBox;Button2: TButton;x: TLabel;znakl: TLabel;znak2: TLabel;procedure FormCreate(Sender: TObject);procedure compClick(Sender: TObject);procedure ButtonlClick(Sender: TObject);procedure Button2Click(Sender: TObject);

private{ Private declarations }procedure min();procedure max();

public

{ Public declarations }end;

varForml: TForml;num, j, i, kolvo, big, small: integer;maximum, minimum: array [1..100] of integer; (массивы

максимальных и минимальных чисел}

implementation

Page 76: Delphi учимся на примерах

Полный исходный код модуля 75

Листинг 9.1. Продолжениег _ _ _ _ _ _

//процедура нахождения наименьшего числаprocedure TForml.min();begin

for i:=l to kolvo do beginfor j:=l to kolvo do begin

{Если число меньше наименьшего,то оно становится наименьшим}if minimum[j] > small then small := minimum[j];

end;end;

end;

//процедура нахождения наибольшего числаprocedure Tforml.max();var

temp: integer;begin

temp := StrToInt(finish.Text);for i:=l to kolvo do begin

for j:=l to kolvo do beginif temp > maximumfj] then

if maximum[j] > 0 then temp:=maximum[j]; {если числобольше наибольшего...}

end;end;

if ( (temp <> 0) and (temp <> StrToInt(finish.Text)) ) then{... и если число входит в допустимый диапазон,то оно становится наибольшим}

big := temp;end;

procedure TForml.FormCreate(Sender: TObject);begin

Randomize; //включаем генератор случайных чисел//загадываем случайное число из заданного диапазонаnum := Random (StrToInt(finish.Text) -

StrToInt (start.Text)) + StrToInt(start.Text);kolvo := 0; //обнуляем количество попытокbig := StrToInt(finish.Text); //самое большое числоsmall := StrToInt(start.Text); //самое маленькое число

end;

procedure TForml.compClick(Sender: TObject);begin

Page 77: Delphi учимся на примерах

76 Игра "Угадывание чисел"

Листинг 9.1. Продолжение

if сотр.Checked then begin //если флажок установлен//блокируем ввод от второго игрокаch2.Enabled := False;р12.Enabled := False;//включаем ввод от первого игрокаchl.Enabled := True;pll. Enabled :•= True;

endelse begin

//если игра идет с человеком, то//включаем ввод для второго игрока

ch2 .Enabled :• True;р12.Enabled := True;

end;end;

procedure TForml.ButtonlClick(Sender: TObject);begin

if ((StrToInt(finish.Text) > StrToInt(start.Text)) and(StrToInt(start.Text) > 0) and(StrToInt(finish.Text) < 60000))

then (проверяем, не выходит ли заданное пользователем число

за допустимые пределы }

(загадаем случайное число в заданном диапазоне}num :<= Random(StrToInt(finish.Text) -

StrToInt(start.Text)) +StrToInt(start.Text)

else ShowMessage('Неверный диапазон!');//обнуляем все, и придаем программе начальный видznakl.Caption :• '';znak2.Caption := '';chl.Enabled := True;ch2.Enabled := False;pll.Enabled := True;pl2.Enabled := False;x.Caption := 'X';chl.Text !- '0';ch2.Text :- '0';

//ОЧИСТИМ массивы наибольших и наименьших чиселfor i:=l to kolvo+1 dobeginminimum!i] := 0;maximum[i) := 0;

big := StrToInt(finish.Text); //наибольшее число

small :» StrToInt(start.Text); //наименьшее число

Page 78: Delphi учимся на примерах

Полный исходный код модуля 77

Листинг 9.1. Продолжение

end;

kolvo := 0; //количество использованных попытокend;

procedure TForml.Button2Click(Sender: TObject);begin

//увеличиваем количество попыток на единицуkolvo := kolvo + 1;if not сотр.Checked then //если идет игра с человекомbegin

if pll.Enabled then begin //если ход первого игрока//если вариант больше загаданного числа, ставим знак >if StrToInt(chl.Text) > num then znakl.Caption !* '>';//если вариант меньше загаданного числа, ставим знак <if StrToInt(chl.Text) < num then znakl.Caption : = '<';if StrToInt(chl.Text) = num then //если число угаданоbegin

znakl.Caption := ' = '; //изменим знак на "="//вместо знака "X" показываем загаданное числох.Caption !• IntToStr(num);

//выводим сообщение о победе первого игрокаShowMessage('Победил первый игрок!' + #13#10 +

'Число угадано за ' + IntToStr(kolvo) +' попытки')

end;

//передаем ход второму игрокуpll.Enabled := False;chl.Enabled := False;ch2.Enabled := True;pl2.Enabled := True;

Exit; //прерываем выполнение процедурыend;

if pl2.Enabled then begin //если ход второго игрока(сравниваем загаданное число с вариантом второгоигрока и ставим соответствующий знак}

if StrToInt (ch2.Text) > num then znak2.Caption := ' >' ;if StrToInt (ch2.Text) < num then znak2.Caption :- '<';if StrToInt(ch2.Text) - num thenbegin

znak2.Caption := '=';x.Caption := IntToStr(num);ShowMessage('Победил второй игрок!' + #13#10 +

'Число угадано за ' + IntToStr(kolvo) +' попытки')

end;end;

Page 79: Delphi учимся на примерах

78 Игра "Угадывание чисел"

Листинг 9.1. Продолжение

//передаем ход первому игрокур12.Enabled u= False;ch2.Enabled := False;chl.Enabled := True;pll.Enabled := True;Exit;

end;if сотр.Checked then begin //если игра против компьютера

{проверяем вариант первого игрока и ставимсоответствующий знак}

if StrToInt(chl.Text) > num then znakl.Caption : = '>';if StrToInt(chl.Text) < num then znakl.Caption := ' < ' ;if StrToInt(chl.Text) = num thenbegin

znakl.Caption := ' = ';x.Caption := IntToStr(num);ShowMessage('Вы победили!

1 + #13#10 +

'Число угадано за ' + IntToStr(kolvo) +' попытки');

Exi tr-end;

//если вариант первого игрока больше загаданного числа}if znakl.Caption = •>' thenbegin

maximum[kolvo] := StrToInt(chl.Text); {добавляемв массив наибольших чисел вариант первого игрока}

max(); //ищем наибольшее числоend;

//если вариант первого игрока меньше загаданного числа}if znakl.Caption = '<' then begin

minimum[kolvo] := StrToInt(chl.Text); {добавляем числов массив наименьших чисел, выданных первым игроком}

min (); //ищем наименьшее числоend;

//после всех расчетов, компьютер выдает свой вариантch2.Text := IntToStr(Random(big - small) + small);

end;

//проверяем вариант компьютера и ставим соответствующий знакif StrToInt(ch2.Text) > num then znak2.Caption := '>';if StrToInt(ch2.Text) < num then znak2.Caption := '<';if StrToInt(ch2.Text) = num then begin

znak2.Caption := '=';x.Caption := IntToStr(num);ShowMessage('Вы проиграли!' + #13#10 +

'В этот раз победил компьютер!' + #13#10 +

Page 80: Delphi учимся на примерах

Полный исходный код модуля 79

Листинг 9.1. Окончание

end;

end;

end.

1 Число угадано за '

' попытки');

+ IntToStr(kolvo) +

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 0 9.

Page 81: Delphi учимся на примерах

so

Вход в систему

Глава 10

Вход в систему

Постановка задачиРазработать программу, которая осуществляет вход в систему. Ин-

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

Разработка формыСоздайте новый проект Delphi и измените свойства формы согласно

табл. 10.1.

Таблица 10.1. Свойства формы программы входа в систему

Свойство

C a p t i o n

A l i g n

B o r d e r S t y l e

F o r m S t y l e

P o s i t i o n

H e i g h t

W i d t h

Значение

a l C u s t o m

bsNone

f s S t a y O n T o p

p o D e s k t o p C e n t e r

130

130

Пояснение

Очистить заголовок

Запрет на перемещение окна

Убираем границу и заголовок окна

Окно программы будет всегда распо-ложено поверх других окон

Высота

Ширина

Разместите на форме компонент Label категории Standard и изме-ните его свойства согласно табл. 10.2.

Таблица 10.2. Свойства компонента L a b e l

Свойство

C a p t i o n

F o n t . C o l o r

F o n t . S i z e

F o n t . S t y l e

Значение

Logon

c l N a v y

20

[ f s B o l d ]

Пояснение

Надпись метки

Цвет текста — темно-синий

Размер шрифта

Начертание шрифта — полужирное

Page 82: Delphi учимся на примерах

Разработка программного кода 81

Таблица 10.2. Окончание

Свойство

L e f t

Тор

Значение

16

0

Пояснение

Отступ слева

Отступ сверху

Разместите под меткой компонент Edit категории Standard и при-свойте его свойству Name значение pass. Для того чтобы скрыть вводтекста (то есть, вводимый пользователем пароль), следует указать всвойстве PasswordChar символ, который будет отображаться вместовводимого текста. Можно указать здесь символ "*" или, например, знакдоллара"$".

Под полем pass разместите кнопку (компонент Button категорииStandard) и присвойте ее свойству Caption значение Enter. По нажа-тию этой кнопки будет выполняться проверка корректности пароля.

Еще нам потребуется два компонента Timer категории System. Дляпервого таймера необходимо изменить значение свойства I n t e r v a l на10, для второго никаких свойств изменять не нужно.

Результат оформления формы должен соответствовать рис. 10,1.

Рис. 10.1. Форма для программы входа в систему

Разработка программного кодаОбъявим в качестве закрытых членов класса формы переменную

процедуры, которые разработаем чуть позже:typeTForml = class(TForm)

private{ Private declarations }hi: HWND; //переменная, содержащая идентификатор окнаprocedure logon(); //блокирует все, пока пароль не будет

6 —5-I2I2

Page 83: Delphi учимся на примерах

82 Вход в систему

//введен верноprocedure check(); //проверка корректности пароля

public{ Public declarations }

end;

Теперь в разделе implementation создадим сами процедуры. Сна-чала процедура check:procedure TForml.check() ;begin

if pass.Text = 'password1 then //если пароль верный

begin

//узнаем идентификатор Рабочего столаhi := FindWindow('Progman', nil);//разрешаем работу с Рабочим столомShowWindow(hi, sw_show);// узнаем идентификатор панели задачhi := FindWindow('Shell_traywnd', nil);//разрешаем работу с панелью задачShowWindow(hi, sw_show);

halt; //закрываем программуend // иначе, выводим сообщение о неверном паролеelse ShowMessage('Wrong password!');

end;

Процедура check проверяет корректность пароля. В данном случаев качестве пароля используется слово "password". Если в поле pass вве-дено именно это слово, то разблокируем Рабочий стол и панель задач.После этого доступ ко всему открыт, и мы завершаем работу програм-мы. Если же введенный пользователем текст не совпадает с корректнымпаролем, то мы продолжаем требовать ввод пароля.

Теперь очередь процедуры logon:procedure TForml.logon();begin

//узнаем идентификатор Рабочего столаhi := FindWindow('Progman', nil);ShowWindow(hi, sw_hide); //прячем Рабочий стол//находим панель задачhi := FindWindow('Shell_traywnd', nil);ShowWindow(hi, sw_hide); //прячем панель задач{проверяем, не запущен ли диспетчер задач}hi := FindWindow(nil, 'Диспетчер задач Windows');(если да, то закрываем окно диспетчера задач}if (hi О 0) then PostMessage(hi, WM_QUIT, 1, 0);

end;

Page 84: Delphi учимся на примерах

Разработка программного кода 83

Здесь мы блокируем Рабочий стол и панель задач, а затем проверя-ем, не пытается ли пользователь отключить нашу программу с помощьюдиспетчера задач. Если окно диспетчера задач открыто, то закрываемего.

Теперь нам почти не придется программировать — мы просто бу-дем вызывать процедуры check и logon. При нажатии кнопки Enter вы-

procedure TForml.ButtonlClick(Sender: TObject);begin

check;end;

Для того чтобы не утруждать пользователя нажатиями кнопки наформе, имитируем эту операцию по нажатию в поле pass клавиши <Еп-ter>. Для этого создайте обработчик события pass . ОпКеуРгеss:procedure TForml.passKeyPress(Sender: TObject; var Key:Char);beginif key = #13 then // если нажата клавиша <Enter>

check; //вызываем процедуру checkend;

#13 — это код клавиши <Enter>.

T V . Коды символов и клавиш клавиатуры перечислены в приложении А.

Для первого таймера событие OnTimer будет содержать только вы-зов процедуры logon:procedure TForml.TimerlTimer(Sender: TObject);beginlogon;

end;

Для второго таймера (у которого свойство I n t e r v a l имеет значе-ние 1000) добавьте в обработчик события OnTimer следующий код:procedure TForml.Timer2Timer(Sender: TObject);beginhi := FindWindow('Progman', nil); //поиск Рабочего столаShowWindow(hi, sw_hide); //прячем Рабочий столCloseWindow(hi); //сворачиваем окно Рабочего столаpass.SetFocus; //переводим курсор в текстовое поле

end;

Сворачивание окна Рабочего стола приводит к закрытию системно-го меню Пуск, если оно открыто. В конечном итоге пользователь неимеет доступа к Рабочему столу, к панели задач, к меню Пуск и диспет-черу задач, однако, несмотря на то, что наша программа не имеет заго-

6*

Page 85: Delphi учимся на примерах

84 Вход в систему

ловка, ее можно закрыть с помощью комбинации клавиш <Alt+F4>. Длятого чтобы отключить эту возможность, создайте обработчик событияглавной формы OnCloseQuery и добавьте в него следующий код:procedure TForml.FormCloseQuery(Sender: TObject;

var CanClose: Boolean);begin

CanClose := False;end;

Единственное, что осталось сделать, —- обеспечить программе авто-загрузку, указав путь к ней в системном реестре. Для работы с реестромнеобходимо добавить в раздел uses ссылку на модуль Registry, а за-тем создать следующий обработчик события формы QnCreate:procedure TForml.FormCreate(Sender; TObject);var

Reg: TRegistry; //переменная для работы с реестром

beginReg !• TRegistry.Create;Reg.RootKey :=> HKEY_CURRENT_USER; //только для текущего

//пользователяReg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',

true);//открываем раздел автозагрузки в реестре//и записываем название и полный путь к нашей программеReg.WriteString('Logon', Application.ExaName);Reg.CloseKey; //закрываем реестрReg.Free; //освобождаем память

end;

Теперь наша программа будет загружаться для текущего пользова-теля вместе с системой и требовать ввод пароля. Программа в действиипоказана на рис. 10.2.

Рис. 10.2. Программа Вход в систему в действии

Page 86: Delphi учимся на примерах

Полный исходный код модуля 85

Полный исходный код модуляПолный исходный код модуля программы Вход в систему представ-

лен в листинге 10.1.

Листинг 10.1. Модуль программы Вход в систему

unit Unitl;

interface

uses

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

typeTForml • class(TForm)

pass: TEdit;

Labell: TLabel;Timerl: TTimer;Buttonl: TButton;Timer2: TTimer;procedure ButtonlClick(Sender: TObject);procedure passKeyPress(Sender: TObject; var Key: Char);procedure FormCloseQuery(Sender: TObject;

var CanClose: Boolean);procedure FormCreate(Sender: TObject);procedure TimerITimer(Sender: TObject);procedure Timer2Timer(Sender: TObject);

private. { Private declarations }

hi: HWND; //переменная, содержащая идентификатор окнаprocedure logon(); //блокирует все, пока пароль не будет

//введен верноprocedure check(); //проверка корректности пароля

public{ Public declarations }

end;

var

Forml: TForml;

implementation

{$R *.dfm}

Page 87: Delphi учимся на примерах

86 Вход в систему

4стинг10.1. Продолжение

procedure TForml.check();begin

if pass.Text = 'password' then //если пароль верныйbegin

//узнаем идентификатор Рабочего столаhi := FindWindow('Progman', nil);//разрешаем работу с Рабочим столомShowWindow(hi, sw_show);// узнаем идентификатор панели задачhi := FindWindow('Shell_traywnd', nil);//разрешаем работу с панелью задачShowWindow(hi, sw_show);

halt; //закрываем программуend // иначе, выводим сообщение о неверном паролеelse ShowMessage('Wrong password!');

end;

procedure TForml.logon() ;begin

//узнаем идентификатор Рабочего столаhi := FindWindow('Progman', nil);ShowWindow(hi, sw_hide); //прячем Рабочий стол//находим панель задачhi := FindWindow('Shell^traywnd', nil);

ShowWindow(hi, sw_hide); //прячем панель задач{проверяем, не запущен ли диспетчер задач}

hi := FindWindow(nil, 'Диспетчер задач Windows');

{если да, то закрываем окно диспетчера задач}if (hi о 0) then PostMessage(hi, WM_QUIT, 1, 0);

end;

procedure TForml.TimerlTimer(Sender: TObject);begin

logon;end;

procedure TForml.ButtonlClick(Sender: TObject);begin

check;end;

procedure TForml.passKeyPress(Sender: TObject; var Key:Char)begin

if key=#13 then // если нажата клавиша <Enter>check; //вызываем процедуру check

Page 88: Delphi учимся на примерах

Полный исходный код модуля 87

Листинг 10.1. Окончание

[ end;

procedure TForml.FormCloseQuery(Sender: TObject;

var CanClose: Boolean);begin

CanClose := False;end;

procedure TForml.FormCreate(Sender: TObject);var

Reg: TRegistry; //переменная для работы с реестромbeginReg := TRegistry.Create;

Reg.RootKey := HKEY_CURRENT_USER; //только для текущего//пользователя

Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',true);//открываем раздел автозагрузки в реестре

//и записываем название и полный путь к нашей программеReg.WriteString('Logon' , Application.ExeName);

Reg.CloseKey; //закрываем реестрReg.Free; //освобождаем память

end;

procedure TForml.Timer2Timer(Sender: TObject);beginhi := FindWindow('Progman', nil); //поиск Рабочего столаShowWindow(hi, sw_hide); //прячем Рабочий столCloseWindow(hi); //сворачиваем окно Рабочего столаpass.SetFocus; //переводим курсор в текстовое поле

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ 1 0 .

Page 89: Delphi учимся на примерах

88 Информация о памяти

Глава 1

Информация1

о памяти

Постановка задачиРазработать программу, которая отображает информацию о физиче-

ской, страничной и виртуальной памяти.

Разработка формыСоздайте новый проект Delphi и присвойте свойству Caption фор-

мы значение Memory Info.Для вывода различной информации о памяти мы будем использо-

вать компонент Label категории Standard. Разместите на форме одиннад другим семь таких компонентов, присвоив свойству Left каждогоиз них значение 230, а свойству Caption — значение 0.

Слева от этого столбца меток разместите в столбец еще семь ком-понентов Label, которые будут пояснять числа, отображаемые преды-дущими семью метками. Присвойте их свойству Caption следующиезначения (сверху вниз): Загруженность памяти:, Все-го физической:, Свободно физической:, Всего страничной:.Свободно страничной:,Всего swap: И Свободно swap:.

Еще одним способом отображения загруженности физической па-мяти будет компонент Gauge категории Samples. Разместите этот ком-понент вдоль правого края формы и измените значение его свойстваKind на gkVerticalBar, чтобы изменения свойства Gauge . Progressотображались вдоль вертикальной шкалы.

Теперь обеспечим настройку автообновления данных о памяти. Дляэтого нам понадобится компонент Timer категории System. Пользова-тель будет задавать период обновления информация о памяти, с помо-щью компонента SpinEdit категории Samples. В его свойствах следуетизменить значение MaxValue на 60, a MinValue —* на 1. Это даст воз-можность пользователю задавать диапазон обновления от 1 до 60 се-кунд.

Page 90: Delphi учимся на примерах

Разработка программного кода 89

Слева от компонента SpinEdit разместите поясняющую метку стекстом Частота обновления :, а справа — метку с текстом секунд.

В правом нижнем углу формы разместите кнопку (компонент But-ton категории Standard) и присвойте ее свойству Caption значение Ус-тановить. По нажатию этой кнопки будет устанавливаться указанная вкомпоненте SpinEdit частота обновления информации.

Полученная форма должна соответствовать рис. 11.1.

Memory info

^Загруженность памяти:

••iBcero физической:

•;: Свободно фИЗИЧеСКОЙ: :

iiiBcero страничной:

•:! Свободно с траничной: •

М:Всего swap: i

::: СвобоДНО Swap: :;

;Частота обновлений: -:ГГ -Й ;секунд Установить

Рис. 11.1. Форма для отображения информации о памяти компьютера

Разработка программного кодаВ программе будет только две процедуры: первая - - обработчик

события Timerl . OnTimer, которая определяет и отображает информа-цию о памяти; вторая — обработчик события OnClick кнопки Устано-вить для задания частоты обновления информации.

Создадим вначале главную часть программы — обработчик собы-тия Timer l .procedure TForml.TimerITimer(Sender: TObject);var

mem: TMemoryStatus; //хранит всю информацию о памятиbeginmem.dwLength := SizeOf(mem); //размер памятиGlobalMemoryStatus(mem); //узнаем всю информацию о памяти//выводим информацию в соответствующие метки

Page 91: Delphi учимся на примерах

90 Информация о памяти

with mem do begin// Загруженность памятиLabell.Caption : = IntToStr(dwMemoryLoad) + ' %';Label2.Caption := IntToStr((dwTotalPhys) div 1024) +

1 Кбайт'; // Всего физической

Label3.Caption := IntToStr ((dwAvailPhys) div 1024) +1 Кбайт'; // Свободно физической

Label4.Caption := IntToStr((dwTotalPageFile) div 1024) +1 Кбайт'; // Всего страничной

Label5.Caption := IntToStr((dwAvailPageFile) div 1024) +1 Кбайт'; // Свободно страничной

Label6.Caption := IntToStr((dwTotalVirtual) div 1024) +1 Кбайт

1; // Всего swap

Label7 . Caption := IntToStr ( (dwAvailVirtual) d.iv 1024) +

' Кбайт'; // Свободно swapGaugel.MaxValue := dwTotalPhys; //определяем максимум//отображаем процент загруженности памятиGaugel.Progress := dwTotalPhys - dwAvailPhys;

end;end;

Сначала мы объявляем переменную mem, которая служит для хране-ния информации о памяти, полученной с помощью функции Global-MemoryStatus. После того как мы получили всю необходимую инфор-мацию о памяти, делим все значения на 1024, чтобы перевести данныев килобайты. Затем выводим информацию с помощью соответствующихметок, а также изменяем текущую позицию для компонента Gauge.

Осталось только реализовать изменение частоты обновления ин-формации, для чего достаточно изменять значение свойстваTimerl . I n t e r v a l . Обработаем нажатие кнопки Установить:procedure TForml.ButtonlClick(Sender: TObject);begin

//установка интервала работы таймераTimerl.Interval := SpinEditl.Value*1000;

end;

Поскольку интервал для таймера задается в мс, а в SpinEdit мывводим значение в секундах, то мы должны умножать значение свойст-ва SpinEdit .Value на 1000.

Программа в действии показана на рис. 11.2.

Полный исходный код модуляПолный исходный код модуля программы отображения информа-

ции о памяти представлен в листинге 11.1.

Page 92: Delphi учимся на примерах

Полный исходный код модуля 91

Memory info

Загруженность памяти:

Всего физической:

Свободно физической:

Все го с тр аничной:

Свободно страничной:

Всего swap:

Свободно swap:

Частота обновлений: Щ "£| секунд

Рис. 11.2. Программа отображения информации о памяти в действии

Листинг 11.1. Модуль программы Memory info

unit Unitl

interface

usesWindows,

I

Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms,

Dialoqs,

typeTForml =

LabellLabel2Label3Label4Label5Label6Label7

GaugelTimerlLabel8Label9

StdCtrls, Gauges, ExtCtrls, Spin;

class(TForm)TLabel;TLabel;TLabel;

TLabel;TLabel;TLabel;TLabel;TGauge;TTimer;TLabel;TLabel;

LabellO: TLabel;Labelll: TLabel;Labell2: TLabel;Labell3: TLabel;

Page 93: Delphi учимся на примерах

92 Информация о памяти

Листинг 11.1. Продолжение

Labell4: TLabel;

SpinEditl: TSpinEdit;Labell5: TLabel;Labell6: TLabel;Buttonl: TButton;procedure TimerlTimer(Sender: TObject);procedure ButtonlClick(Sender: TObject);

private

( Private declarations )public

{ Public declarations )end;

var

Forml: TForml; , •

implementation

{$R *.dfm}

procedure TForml.TimerlTimer(Sender: TObject);varmem: TMemoryStatus; //хранит всю информацию о памяти

begin

mem.dwLength : = SizeOf(mem); //размер памятиGlobalMemoryStatus(mem); //узнаем всю информацию о памяти//выводим информацию в соответствующие меткиwith mem do begin

// Загруженность памяти

Labell.Caption := IntToStr(dwMemoryLoad) + ' %';Label2.Caption := IntToStr((dwTotalPhys) div 1024) +

' Кбайт'; // Всего физическойLabel3.Caption : = IntToStr ((dwAvailPhys) div 1024) +

' Кбайт'; // Свободно физическойLabel4.Caption := IntToStr((dwTotalPageFile) div 1024) +

' Кбайт'; // Всего страничнойLabel5.Caption :- IntToStr((dwAvailPageFile) div 1024) +

1 Кбайт'; // Свободно страничной

Label6.Caption := IntToStr((dwTotalVirtual) div 1024) +' Кбайт

1; // Всего swap

Label7.Caption := IntToStr((dwAvailVirtual) div 1024) +1 Кбайт'; // Свободно swap

Gaugel.MaxValue := dwTotalPhys; //определяем максимум//отображаем процент загруженности памятиGaugel.Progress := dwTotalPhys - dwAvailPhys;

Page 94: Delphi учимся на примерах

Полный исходный код модуля 93

Листинг 11.1. Окончание

епа;

procedure TForml.ButtonlClick(Sender: TObject);begin

//установка интервала работы таймераTimerl.Interval : = SpinEditl.Value*1000;

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ l l .

Page 95: Delphi учимся на примерах

94 Программа настройки Windows

Глава 12

Программа настройки Windows

Постановка задачиРазработать программу, которая осуществляет настройку ОС Win-

dows через реестр.Поскольку ОС Windows не предоставляет возможность полной ви-

зуальной настройки, существует множество программ для "тонкой" на-стройки, этой операционной системы. Например, в Windows XP нельзя,просто "сбросив флажок", отключить автозагрузку с CD-ROM или за-блокировать системный реестр. Все это можно сделать только через ре-естр, что не очень-то удобно. К тому же, запомнить все ключи реестраневозможно, а справочник не всегда оказывается под рукой.

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

Краткий справочник по реестру Windows находится в приложении В.

Разработка формыСоздайте новый проект Delphi. Присвойте свойству Caption фор-

мы значение Настройка ОС windows. Разместите на форме компонентGroupBox категории Standard и присвойте его свойству Caption значе-ние Опции. На компоненте GroupBox разместите один над другим трикомпонента CheckBox категории Standard и присвойте их свойствуCaption следующие значения: Отключить автозагрузку с CD-ROM,Отключить свойства экрана И Заблокировать реестр.У нижнегокрая формы разместите кнопку (компонент Button категории Standard),присвоив ее свойству Caption значение Выполнить.

Полученная форма должна соответствовать рис. 12.1.

Page 96: Delphi учимся на примерах

Разработка программного кода 95

Ш Настройка ОС Win -[.•1..X.IОпцииГ" Отключить автозагрузку е CD-ROM

| Г" Отключить свойства экрана

[ Г" Заблокировать реестр

Выполнить

Рис. 12.1. Форма программы настройки Windows

Разработка программного кодаВ программе потребуется обработать два события: создание формы

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

Для начала добавим в раздел uses ссылку на модуль Regi s t ry дляработы с системным реестром. Также необходимо объявить глобальнуюпеременную reg типа TRegistry, с помощью которой мы будем рабо-тать с реестром:

varForml: TForml;reg: TRegistry;

Обработчик события создания главной формы OnCreate:procedure TForml.FormCreate(Sender: TObject);beginreg := TRegistry.Create; //открываем реестр//настройки для текущего пользователяreg.RootKey := HKEY_CURRENT_USER;reg.OpenKey('SYSTEM\CurrentControlSet\Services\Cdrom',

False); //открываем разделif reg.ValueExists('Autorun

1) then //если ключ существует

if reg.Readlnteger('Autorun') = 1 //и если он равен 1,then //то устанавливаем флажок первой опции

CheckBoxl.Checked := True;reg.CloseKey; //закрываем реестр

//Таким же образом проверяем остальные опции

Page 97: Delphi учимся на примерах

96 Программа настройки Windows

//Для опции "Отключить свойства экрана":reg := TRegistry.Create;reg.RootKey:=HKEY_CURRENT_USER;reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\' +

1Policies\System', False);

if reg.ValueExists('NoDispCPL') then

if reg.Readlnteger('NoDispCPL') = 1

then CheckBox2.Checked i= True;reg.CloseKey;

//для опции "Заблокировать реестр":reg := TRegistry.Create;reg.RootKey : = HKEY_CURRENT_USER;

reg.OpenKey ('Software\Microsoft\Windows\CurrentVersion\' +1Policies\System', False);

if reg.ValueExists('DisableRegistryTools') then

if reg.Readlnteger('DisableRegistryTools') = 1

then CheckBox3.Checked := True;reg.CloseKey;

end;

При создании формы мы проверяем, какие из опций уже установле-ны. Если опция уже установлена, то устанавливаем соответствующийфлажок.

OnClick для кнопки Выполнить:procedure TForml.ButtonlClick(Sender: TObject);begin

if CheckBoxl.Checked then

begin //если установлен флажок напротив первой опцииreg := TRegistry.Create; //открываем реестр//открываем ветку реестраreg.RootKey := HKEY_LOCAL_MACHINE;reg.OpenKey('SYSTEM\CurrentControlSet\Services\Cdrom',

True); //открываем требуемый раздел в реестре//записываем соответствующий ключreg.Writelnteger('Autorun', 1);reg.CloseKey;

end else begin //иначе...

reg := TRegistry.Create;reg.RootKey := HKEY_LOCAL_MACHINE;

reg.OpenKey('SYSTEM\CurrentControlSet\Services\Cdrom',True);

//...отключаем эту возможностьreg.Writelnteger('Autorun

1, 0) ;

reg.CloseKey;end;

L

Page 98: Delphi учимся на примерах

Разработка программного кода 97

//Таким же образом обрабатываем остальные опции

//Для опции "Отключить свойства экрана":if CheckBox2.Checked thenbegin

reg := TRegistry.Create;reg.RootKey:=HKEY_CURRENT_USER;reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'

+ 'Policies\System', True);

//отключить свойства экранаreg.Writelnteger('NoDispCPL', 1);reg.CloseKey;

end else begin

reg := TRegistry.Create;reg.RootKey := HKEY_CURRENT_USER;

reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'+ 'Policies\System', True);

//Восстановить свойства экранаreg.Writelnteger('NoDispCPL', 0) ;reg.CloseKey;

end;

//Для опции "Заблокировать реестр":if CheckBox3.Checked thenbegin

reg := TRegistry.Create;

reg.RootKey := HKEY_CURRENT_USER;

reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'+ 'Policies\System', True);

//Заблокировать реестрreg.Writelnteger('DisableRegistryTools', 1);

reg.CloseKey;end else begin

reg := TRegistry.Create;reg.RootKey := HKEY_CURRENT_USER;

reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'+

TPolicies\System', True);

//открыть доступ к рееструreg.Writelnteger('DisableRegistryTools', 0);reg.CloseKey;

end;end;

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

7 — 5-1.212

Page 99: Delphi учимся на примерах

98 Программа настройки Windows

Теперь можно откомпилировать и запустить программу на выпол-нение. Выберите, например, опцию Заблокировать реестр и нажмитекнопку Выполнить. Чтобы удостовериться в том, что реестр действи-тельно заблокирован, выполните команду системного меню Пуск —> Вы-полнить, в диалоговом окне Запуск программы введите r e g e d i t и на-жмите кнопку ОК. Если вместо окна реестра вы увидите сообщение обошибке "Редактирование реестра запрещено администратором системы"(рис. 12.2), то это значит, что наша программа работает нормально.

Редактирование реестра запрещено администратором системы,

Рис. 12.2. Программа заблокировала системный реестр Windows

После этого опять перейдите в программу Настройка ОС Windows,сбросьте флажок Заблокировать реестр и нажмите кнопку Выполнить.Попробуйте еще раз войти в реестр. Как видите, теперь никаких препят-ствий не возникает.

Полный исходный код модуляПолный исходный код модуля программы настройки Windows

представлен в листинге 12.1.

Листинг 12.1. Модуль программы настройки Windows

unit Unitl;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms,

Dialogs, StdCtrls, Registry;

typeTForml = class(TForm)Buttonl: TButton;GroupBoxl: TGroupBox;

Page 100: Delphi учимся на примерах

Полный исходный код модуля 99

Листинг 12.1. Продолжение

CheckBoxl: TCheckBox;CheckBox2: TCheckBox;CheckBox3: TCheckBox;procedure ButtonlClick(Sender: TObject);procedure FormCreate(Sender: TObject);

private{ Private declarations }

public

{ Public declarations }end;

varForml: TForml;reg: Tregistry;

implementation

{$R *.dfm}

procedure TForml.ButtonlClick(Sender: TObject);begin

if CheckBoxl.Checked thenbegin //если установлен флажок напротив первой опции

reg := TRegistry.Create; //открываем реестр//открываем ветку реестраreg.RootKey := HKEY_LOCAL_MACHINE;reg.OpenKey('SYSTEM\CurrentControlSet\Services\Cdrom',

True); //открываем требуемый раздел в реестре

//записываем соответствующий ключreg.Writelnteger('Autorun' , 1);

reg.CloseKey;end else begin //иначе...

reg := TRegistry.Create;

reg.RootKey := HKEY_LOCAL_MACHINE;reg.OpenKey('SYSTEM\CurrentControlSet\Services\Cdrom',

True);//. . .отключаем эту возможностьreg.Writelnteger('Autorun

1, 0);

reg.CloseKey;end;

//Таким же образом обрабатываем остальные опции

//Для опции "Отключить свойства экрана":if CheckBox2.Checked thenbegin

reg := TRegistry.Create;

7*

Page 101: Delphi учимся на примерах

100 Программа настройки Windows

Листинг 12.1. Продолжение

reg.RootKey:=HKEY_CURRENT_USER;reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'

+ 'Policies\System', True);//отключить свойства экранаreg.Writelnteger('NoDispCPL', 1);

reg.CloseKey;end else begin

reg := TRegistry.Create;reg.RootKey := HKEY_CURRENT_USER;reg.OpenKey('SoftwareXMicrosoft\Windows\CurrentVersion\'

+ 'PoliciesNSystem', True);//Восстановить свойства экранаreg.Writelnteger('NoDispCPL

1 , 0) ;

reg.CloseKey;end;

//Для опции "Заблокировать реестр":

if СпескВохЗ.Checked thenbegin

reg :« TRegistry.Create;reg.RootKey := HKEY_CURRENT_USER;reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'

+ 'Policies\System', True);//Заблокировать реестрreg.Writelnteger('DisableRegistryTools', 1);reg.CloseKey;

end else begin

reg : = TRegistry.Create;reg.RootKey := HKEY_CURRENT_USER;

reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\'+ 'PoliciesXSystem', True);

//открыть доступ к рееструreg.Writelnteger('DisableRegistryTools', 0);reg.CloseKey;

end;end;

procedure TForml.FormCreate(Sender: TObject);begin

reg := TRegistry.Create; //открываем реестр//настройки для текущего пользователя

reg.RootKey := HKEY_CURRENTJJSER;reg.OpenKey('SYSTEM\CurrentControlSet\Services\Cdrom',

False); //открываем разделif reg.ValueExists('Autorun') then //если ключ существует

Page 102: Delphi учимся на примерах

Полный исходный код модуля 101

Листинг 12.1. Окончание

if teg.Readlnteger('Autorun') = 1 //и если он равен 1,then //то устанавливаем флажок первой опции

CheckBoxl.Checked := True;reg.CloseKey; //закрываем реестр

//Таким же образом проверяем остальные опции

//Для опции "Отключить свойства экрана":reg := TRegistry.Create;reg.RootKey:=HKEY_CURRENTJJSER;reg. OpenKey ( ' Sof tware\Microsoft\-Windows\CurrentVersion\ ' +

1PoliciesXSystem', False);

if reg.ValueExists('NoDispCPL') then

if reg.Readlnteger('NoDispCPL1) = 1

then CheckBox2.Checked := True;reg.CloseKey;

//для опции "Заблокировать реестр":reg := TRegistry.Create;reg.RootKey := HKEY_CURRENT_USER;reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\' +

'PoliciesXSystem', False);if reg.ValueExists('DisableRegistryTools') then

if reg.Readlnteger('DisableRegistryTools') = 1then CheckBox3.Checked := True;

reg.CloseKey;end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 12.

Page 103: Delphi учимся на примерах

102 Тест

Глава 13

Тест

Постановка задачиРазработать программу для тестирования знаний в разных областях.

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

Структура базы вопросов и ответов

Перед тем как разработать сам тест, разберем содержимое файла,в котором будут храниться вопросы и варианты ответов к ним. Это бу-дет ini-файл следующей структуры:

[num]гшт=количество вопросов в базе

[Q]0=Первый вопрос1=Второй вопрос

[А]О=0твет к первому вопросу1=0твет ко второму вопросу

[W1]О=Неправильный вариант к первому вопросу1= Неправильный вариант ко второму вопросу

[W2]О=Неправильный вариант к первому вопросу1= Неправильный вариант ко второму вопросу

Page 104: Delphi учимся на примерах

Разработка формы 103

[W3]

О=Неправильный вариант к первому вопросу

1= Неправильный вариант ко второму вопросу

В этом ini-файле шесть разделов: num, Q, A, wi, W2 и W3. Как вы по-нимаете, если кто-то заглянет в этот файл, то уже через несколько минутон будет знать правильные ответы на все вопросы. А если он этот файлподкорректирует, то и вовсе будет получать только правильные вариан-ты ответов. Для того чтобы этого не случилось, мы будем шифроватьнашу базу вопросов. Это можно сделать с помощью программы Блок-нот-шифровальщик, рассмотренной в главе 7. Для шифрования выберемнебольшое смещение, например, 101. После того как вы создали все во-просы и варианты ответов к ним, не забудьте указать количество вопро-сов в разделе num. После этого зашифруйте базу, используя смещение101.

Пример зашифрованной базы вопросов/ответов можно найти на прилагаемом ккниге компакт-диске в файле C h a p t e r _ 1 3 \ c o m p . i n i .

Разработка формыСоздайте новый проект Delphi. Присвойте свойству Caption фор-

мы значение Tester, а свойству BorderStyle — bsNone. У верхнегокрая формы разместите компонент Label категории Standard, присвоивего свойству Caption значение Первый вопрос :.

Ниже разместите компонент Memo категории Standard, с помощьюкоторого мы будем отображать текущий вопрос. Присвойте свойствуMemol .Readonly значение True, чтобы пользователь не мог изменитьтекст вопроса.

Под вопросом будут расположены варианты ответов. Разместитепод компонентом Memol компонент RadioGroup (группа переключате-лей) категории Standard и присвойте его свойству Caption значениеВарианты ответов:. Разместите на компоненте RadioGroupl четырекомпонента RadioButton (переключатели) категории Standard. Очисти-те для каждого из них свойство Caption, а свойству Name присвойтезначения anl, ап2, апЗ и ап4 соответственно.

В любом месте формы разместите компонент Label, который изна-чально будет невидимым. Он будет служить для отображения результа-тов и в последствии будет растянут на всю форму. Установите для негосвойства согласно табл. 13.1.

Page 105: Delphi учимся на примерах

104 Тест

Таблица 13.1. Свойства компонента L a b e l , отображающего результат теста

Свойство

Al ignment

Color

F o n t . C o l o r

Font.Name

Font .S ize

F o n t . S t y l e

V i s i b l e

Значение

taCenter

c l B l a c k

clRed

A r i a l

26

[ f s B o l d ]

False

Пояснение

Выравнивание текста — по центру

Цвет фона — черный

Цвет текста — красный

Название шрифта

Размер шрифта

Начертание шрифта — полужирное

При запуске программы метка невидима

Осуществлять переход к следующему вопросу мы будем с помо-щью панелей. Разместите под вариантами ответов пять компонентовPanel категории Standard. Для каждой из них присвойте свойству Cap-t i o n значение Следующий вопрос>>>>>, свойству Color — значениеclMaroon, а свойству Font. Color — значение clWhite. Присвойте имимена (свойство Name) pi, р2, рЗ, р4 и р5. Для того чтобы убрать вы-пуклость и привести панель к виду стильной кнопки, изменим значениесвойства Bevel lnner на bvRaised, а свойства BevelOuter — наbvLowered. Для всех панелей, кроме pi, присвойте свойству Vis ib leзначение False (изначально будет видна только первая панель).

Поскольку в программе будет предусмотрена возможность динами-ческой загрузки базы вопросов/ответов, нам понадобится диалоговоеокно открытия файла. Для этого разместим на форме компонент Open-Dialog категории Dialogs и присвоим ему имя Openl (свойство Name).Кроме того, определите в свойстве F i l t e r следующий фильтр: i n i -ф а й л ы | * . i n i | В с е файлы|*.*.

Теперь разработаем меню про-граммы. Для этого разместите наформе компонент MainMenu катего-рии Standard и создайте меню в со-ответствии с рис. 13.1.

Разработка меню рассматриваетсяв главе 6, "Программа просмотра ри-сунков".

Полученная форма должнапримерно соответствовать рис. 13.2.

Игра ; |

Заново

Загрузить вопросы

Выход

•г::: : уРис. 13.1. Меню для программы-теста

Page 106: Delphi учимся на примерах

Разработка программного кода 105

]fo TesterИгра

. ТТсрсый ьопрос:

;<:М:»

ж\

Варианты ответов:

Г г

Следующий вопрос"I

Рис. 13.2. Форма программы-теста

Разработка программного кодаДля начала, объявим все глобальныепеременные:

varForml: TForml;i, a, n, balls, vopr: integer; {различные счетчики и

переменные для подсчета баллов}dir, dir2, ss, zz, yes: string; (путь к файлу с вопросами,

к программе и расшифрованной базе}win: TIniFile; //переменная для работы с ini-файламиmass: array[1..100] of integer; {содержит номера уже

заданных вопросы, чтобы они не повторялись }f1, f2: file of char; //переменные для работы с файламисор: char; //для работы с каждым символом отдельно

Добавим в раздел uses ссылку на модуль IniFiles, который потребу-ется для работы с классом T I n i F i l e . Мы также разработаем четыресобственные процедуры. Объявим их как закрытые члены класса фор-мы:

typeTForml = class(TForm)

private

Page 107: Delphi учимся на примерах

106 Тест

{ Private declarations }procedure start; //начало тестаprocedure question_select; //выбор вопросаprocedure vars(var variant: integer); {сортировка и

определение правильного варианта ответа}procedure verno(); {проверка: правильно ли ответил

пользователь}public

Public declarations }end;

Теперь создадим сами процедуры в разделе implementation. Про-

procedure TForml.start();begin

Randomize; //Включаем генератор случайных чиселfor i:=l to n do mass[i] := 0; I In - количеству вопросов{$1-} //отключаем контроль ошибок ввода/вывода.//делаем все элементы видимыми для пользователяMemol.Visible := True;RadioGroupl.Visible := True;Labell.Visible := True;

an1.Visible := True;an2.Visible := True;

an3.Visible := True;

an4.Visible := True;

pi.Visible := True;

p2.Visible := False;

p3.Visible := False;

p4.Visible := False;

p5.Visible := False;balls := 0;

Label2.Visible := False; //прячем результатыLabell.Caption := 'Первый вопрос:

1;

dir2 := 'C:\base.bsd'; //путь к расшифрованной базе//копируем зашифрованную базу на диск С:CopyFile(PChar(ss), PChar(dir2), True);//связываем переменную fl с зашифрованным ini-файломAssignFile(fl, ss) ;//связываем переменную f2 с файлом C:\base.bsdAssignFile(f2, dir2);

Reset(fl); //открываем первый файл на чтениеRewrite(f2); //второй - на записьwhile not Eof(fl) do

begin //пока не достигнут конец первого файлаRead(fl, cop); //считываем один символ из файласор :•* Chr(Ord(cop) xor 101); //расшифровываем символ

Page 108: Delphi учимся на примерах

Разработка программного кода 107

Write(f2, сор); //записываем расшифрованный символ в файлend;CloseFile (f1) ; //закрываем первый файлCloseFile(f2); //закрываем второй файл{$1+} //включаем контроль ошибок ввода/выводаWin := TIniFile.Create(dir2); //работаем с ini-файлом//считываем количество вопросов в базеss := Win.ReadString('num', 'num', ss);

//преобразовываем строку в число и записываем значение в пn := StrToInt(ss);vopr := Random(4) + 1; //случайное число от 1 до 4vars(vopr); {передаем число процедуре vars, которая

сортирует варианты ответов}end;

Эта процедура начинает игру. Сначала делаем все элементы види-мыми и прячем метку, отображающую результат прохождения теста.Затем открываем файл, содержащий вопросы, и считываем из него поодному символу. Каждый байт расшифровывается особо и записываетсяв отдельный файл. Далее мы работаем с расшифрованным файлом как собычным ini-файлом. Первое, что мы считываем, — это общее количе-ство вопросов в базе.

^ТГепе£ь очередь процедуры ques t ion s e l e c t :procedure TForml.question_select() ;label ran; //метка ran для быстрого переходаbegin

Randomize;ran:a := Random(n); //выбираем случайный вопрос из базы//проверяем: не задавали ли мы этот вопрос ранееfor i:=1 to n do

if mass[i] = a then goto ran;for i:=1 to n do

if mass[i] = 0 thenbegin

mass[i] := а; {записываем номер вопроса, чтобы незадавать его больше }

Break;end;

//сбрасываем флажки со всех вариантов ответаanl.Checked := False;an2.Checked := False;апЗ.Checked := False;an4.Checked := False;

end;

Page 109: Delphi учимся на примерах

108 Тест

Эта процедура случайным образом выбирает вопрос. Затем выпол-няется проверка: не задавался ли этот вопрос ранее. Если мы нашли во-прос, который еще не был задан, то задаем его и помечаем как уже за-данный, чтобы не задавать его больше в текущей сессии.

procedure TForml.verno();begin

if anl.Checked thenif yes = anl.Caption

if an2.Checked thenif yes = an2.Caption

if an3.Checked thenif yes = an3.Caption

if an4.Checked thenif yes = an4.Caption

end;

then

then

then

then

balls :

balls :

balls :

balls :

= balls

= balls

• balls

= balls

+

+

+

+

if

1;

1;

1;

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

procedure TForml.vars(var variant: integer);begin

//вызываем процедуру выбора случайного вопросаquestion_select();case variant of

1: begin

Win := TIniFile.Create(dir2); //открываем ini-файл//считываем вопросMemol.Text :=Win.ReadString('Q', IntToStr(a), Memol.Text);

//считываем правильный вариант ответаanl.Caption :=

Win.ReadString('A', IntToStr(a), anl.Caption);//считываем три неверных варианта к данному вопросуan2.Caption :=

Win.ReadString('Wl', IntToStr(a), an2.Caption);an3.Caption :=Win.ReadString(•W2', IntToStr(a), an3.Caption);

an4.Caption :=

Win.ReadString('W3', IntToStr(a), an4.Caption);Win.Free; //освобождаем ini-файл//помечаем первый вариант как правильныйyes := anl.Caption;

end;2 : begin

Page 110: Delphi учимся на примерах

Разработка программного кода 109

Win := TIniFile.Create(dir2);Memo1.Text :=Win.ReadString('Q',

an2.Caption :=Win.Readstring('A',

anl.Caption :=Win.Readstring('Wl'

an3.Caption :=Win.ReadString(•W2'

an4.Caption :=

Win.ReadString(•W3'Win.Free;yes := an2.Caption;

end;3: begin

IntToStr(a),

IntToStr(a),

, IntToStr(a)

, IntToStr(a)

, IntToStr(a)

Win := TIniFile.Create(dir2);

Memol.Text :=Win.ReadString('Q',

an3.Caption :=

Wxn.ReadString('A',an2.Caption :=Win.ReadString('Wl

1

anl.Caption :=Win.ReadString( 'W2'

an4.Caption :=

Win.ReadString('W3•Win.Free ;yes := an3.Caption;

end;4: begin

IntToStr(a),

IntToStr(a),

, IntToStr(a)

, IntToStr(a)

, IntToStr(a)

Win := TIniFile.Create(dir2);Memol.Text :=

Win.ReadString('Q',an4.Caption :=

Win.ReadString('A',an2.Caption :=Win.ReadString('Wl

1

an3.Caption :=Win.ReadString('W2'

anl.Caption :=Win.ReadString('W3'

Win.Free;yes := an4.Caption;

end;end;

end;

IntToStr(a),

IntToStr(a),

, IntToStr(a)

, IntToStr(a)

, IntToStr(a)

Memol.Text);

an2.Caption);

, anl.Caption);

, an3.Caption);

, an4.Caption);

Memol.Text);

an3.Caption);

, an2.Caption);

, anl.Caption);

, an4.Caption);

Memol.Text);

an4.Caption);

, an2.Caption);

, an3.Caption);

, anl.Caption);

Page 111: Delphi учимся на примерах

ПО Тест

Здесь мы вначале запускаем процедуру выбора вопроса. Потом про-веряем: какой вариант ответа является правильным. Затем считываемвопрос и варианты ответов к нему. Сортируем и отображаем все это наформе.

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

procedure TForml.FormCreate(Sender: TObject);begin

Randomize;//получаем каталог, в котором находится наша программаdir := GetCurrentDir;ss := dir + '\comp.ini'; //путь к базе вопросовzz := ss;start(); //начинаем тест

end;

Теперь создадим обработчик события главной формы OnDestroy

522Ei?KJLeTJIE!L5£™ r *--'".', •'""''procedure TForml.FormDestroy(Sender: TObject);begin

DeleteFile('c:\base.bsd'); //удаляем расшифрованную базуend;

Теперь обрабатываем команды меню. Обработчик события OnClickдля пункта Игра -» Заново:г— * • '

procedure TForml.NIClick(Sender: TObject);beginRandomize;

ss := zz;

start(); //начало тестаend;

Поскольку у нас весь основной код вынесен в процедуры, теперьдостаточно только вызвать процедуру начала игры.

Обработчик события OnClick для пункта меню Игра-» Загрузитьбазу:procedure TForml.N2Click(Sender: TObject);beginRandomize;

//начинаем обзор с текущего каталогаOpenl.InitialDir := GetCurrentDir;if not Openl.Execute

then ShowMessage('Вы не выбрали файл!')else begin

ss := Openl.FileName; //открываем выбранный файл

Page 112: Delphi учимся на примерах

Разработка программного кода 111

zz := ss; //запоминаем путь к базеstart(); //начинаем тест

end;

end;

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

Обработчик события OnClick Для rryHKTajwej4ro_Jrfrpa —*_Выход:procedure TForml.N4Click(Sender: TObject);begin

Halt; //выход из программыend;

Теперь обработаем щелчок мышью на панели p i :procedure TForml.plClick(Sender: TObject);begin

Label1.Caption := 'Второй вопрос:';verno(); //принимаем вариант ответаpi.Visible := False; //убираем первую панельр2.Visible := True; //активизируем вторую панельvopr := Random(4) + 1; //выбираем случайный вариант ответаvars(vopr); //задаем вопрос

end;

Здесь мы вначале изменяем заголовок на "Второй вопрос:", послечего принимаем вариант ответа, выбранный пользователем, вызываяпроцедуру verno. Затем готовим форму ко второму вопросу: прячемпервую панель и выводим вторую. Вызываем процедуру vars, котораявыбирает вопрос и отображает его вместе с вариантами ответа.

procedure TForml.p2Click(Sender: TObject);beginLabel1.Caption := 'Третий вопрос:';verno();

p2.Visible := False;

p3.Visible := True;

vopr := Random(4) + 1;

vars(vopr);end;

Здесь происходит то же самое, что и для панели pi, только надписьметки принимает значение "Третий вопрос", мы прячем вторую "кноп-ку" и активизируем третью для следующего вопроса.

Page 113: Delphi учимся на примерах

112 Тест

Аналогичные обработчики события OnClick создаем для третьей ичет^вертгойпанелей:procedure TFormlbegin

Labell.Captionverno();p3.Visible :=p4.Visible :=

.p3Click(Sender: TObject);

:= 'Четвертый вопрос:';

False;True ;

vopr :• Random(4) + 1;vars(vopr);

end;

procedure TFormlbegin

Labell.Caption

verno();

p4.Visible :=

p5.Visible :=

.p4Click(Sender: TObject);

:= 'Пятый вопрос:';

False;

True;vopr := Random(4) + 1;vars(vopr);

end;

Для пятой (последней) панели обработчик события OnClick будет

procedure TForml.p5Click(Sender: TObject);begin

//проверяем правильность ответа на последний вопросverno();//узнаем, сколько баллов набрал пользовательss := IntToStr(balls);//делаем почти все компоненты невидимымиMemol.Visible := False;р5.Visible := False;RadioGroupl.Visible := False;

Labell.Visible := False;

anl.Visible := False;

an2.Visible := False;

an3.Visible := False;

an4.Visible := False;

Label2.Visible := True; //показываем метку с результатомLabel2.Align := alClient; //растягиваем ее на всю форму//Отображаем процент правильных ответовLabel2.Caption := 'Правильных ответов' +

IntToStr(balls*(100 div 5))+'%';end;

Page 114: Delphi учимся на примерах

Разработка программного кода 113

После проверки правильности ответа на последний вопрос, мы пря-чем почти все компоненты на форме, оставляя видимой только меткуLabel2 для вывода результата и меню, чтобы можно было продолжитьработу с программой. С помощью метки мы отображаем процент пра-вильных ответов пользователя по формуле: "количество правильныхответов * (100 / количество заданных вопросов)". Пример отображениярезультата теста представлен на рис. 13.3.

Рис. 13.3. Отображение результата теста

Единственное, что осталось сделать, — реализовать имитацию на-жатия кнопки при щелчке на панели мышью. Для того чтобы "оживить"панель, для нее следует создать обработчики двух событий: OnMouse-Down и OnMouseUp. Первое событие возникает при щелчке мышью, авторое — при отпускании кнопки мыши. Для панели pi эти обработчи-K H J ? J > S ! O L i ! M L ^ ^ _______ _I procedure TForml.plMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);beginpi.Bevellnner := bvLowered;pi.BevelOuter := bvRaised;

end;

I procedure TForml.plMouseUp(Sender: TObject;I Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

8 — 5-1212

Page 115: Delphi учимся на примерах

114 Тест

beginpi.Bevellnner:pi.BevelOuter:

end;

=bvRaised;=bvLowered;

Для всех остальных панелей обработчики этих событий будут вы-глядеть аналогичным образом за исключением того, что имя p i потре-буется изменить на имя р2, рз, р4 или р5.

Программа тестирования в действии показана на рис. 13.4.

Игра

Первый еопрос:

Какой из этих циклов отсутствует в Delphi?

Варианты: от бет он:

Г foi

Г while

{•" ,'foreacl

С repeat

Следующий вопроо»;

Рис. 13.4. Программа тестирования в действии

Полный исходный код модуляПолный код модуля программы-теста представлен в листинге 13.1.

Листинг 13.1. Модуль программы-теста

unit Unitl;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, ExtCtrls, StdCtrls, inifiles,jpeg, Menus;

type

Page 116: Delphi учимся на примерах

Полный исходный код модуля 115

Листинг 13.1. Продолжение

TForml = class(TForm)Memo1: TMemo;RadioGroupl: TRadioGroup;pi: TPanel;p2: TPanel;p3: TPanel;p4 : TPanel;p5 : TPanel;anl: TRadioButton;an2: TRadioButton;an3: TRadioButton;an4: TRadioButton;Label1: TLabel;Label2: TLabel;MainMenul: TMainMenu;N1: TMenuItera;N2: TMenuItem;N3: TMenuItem;N4: TMenuItem;Openl: TOpenDialog;procedure FormCreate(Sender: TObject);procedure plClick(Sender: TObject);procedure p2Click(Sender: TObject);procedure p3Click(Sender: TObject);procedure p4Click(Sender: TObject);procedure p5Click(Sender: TObject);procedure ImagelClick(Senderprocedure plMouseDown(SenderButton: TMouseButton; Shift:procedure plMouseUp(Sender:Button: TMouseButton; Shift:procedure p2MouseDown(SenderButton: TMouseButton; Shift:procedure p2MouseUp(Sender:Button: TMouseButton; Shift:procedure p3MouseDown(SenderButton: TMouseButton; Shift:procedure p3MouseUp(Sender:Button: TMouseButton; Shift:procedure p4MouseUp(Sender:Button: TMouseButton; Shift:procedure p4MouseDown(SenderButton: TMouseButton; Shift:procedure p5MouseDown(SenderButton: TMouseButton; Shift:

: TObject);: TObject;TShiftState;TObject;TShiftState;: TObject;TShiftState;TObject;TShiftState;: TObject;TShiftState;TObject;TShiftState;TObject;TShiftState;: TObject;TShiftState;: TObject;TShiftState;

x,

x,

x,

x,

x,

x,

x,

x,

x,

Y:

Y:

Y:

Y:

Y:

Y:

Y:

Y:

Y:

Integer);

Integer);

Integer);

Integer);

Integer);

Integer);

Integer);

Integer);

Integer);

Page 117: Delphi учимся на примерах

116 Тест

Листинг 13,1. Продолжение

procedure p5MouseUp(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);procedure NIClick(Sender: TObject);procedure N2Click(Sender: TObject);procedure N4Click(Sender: TObject);procedure FormDestroy(Sender: TObject);

private

( Private declarations }procedure start; //начало тестаprocedure question_select; //выбор вопросаprocedure vars(var variant: integer); {сортировка и

определение правильного варианта ответа }procedure verno(); {проверка: правильно ли ответил

пользователь}public

{ Public declarations }end;

varForml: TForml;i, a, n, balls, vopr: integer; {различные счетчики и

переменные для подсчета баллов)dir, dir2, ss, zz, yes: string; {путь к файлу с вопросами,

к программе и расшифрованной базе}win: TIniFile; //переменная для работы с ini-файламиmass: array[1..100] of integer; {содержит номера уже

заданных вопросов, чтобы они не повторялись }fl,f2: file of char; //переменные для работы с файламисор: char; //для работы с каждым символом отдельно

implementation

{$R *.dfm}

procedure TForml.vars(var variant: integer);begin

//вызываем процедуру выбора случайного вопросаquestion_select();case variant of

1: begin

Win := TIniFile.Create(dir2); //открываем ini-файл//считываем вопросMemol.Text :=

Win.ReadString('Q', IntToStr(a), Memol.Text);//считываем правильный вариант ответаanl.Caption :=

Page 118: Delphi учимся на примерах

Полный исходный код модуля 117

Листинг 13.1. Продолжение

Win.Readstring('A', IntToStr(a),

//считываем три неверных варианта

an2.Caption :=

Win.ReadString('

апЗ.Caption : =

Win.ReadString('

an4.Caption :=

Win.ReadString('

Wl1 ,

W2',

W3' ,

IntToStr(a)

IntToStr(a)

IntToStr(a)

Win.Free; //освобождаем ini-файл

//помечаем первый

yes := anl.Caption

end;

2 : begin

anl.Caption);

к данному вопросу

, an2.Caption);

, апЗ.Caption);

, an4.Caption);

вариант как правильный

;

Win := TIniFile.Create

Memol.Text :=

Win.ReadString('

an2.Caption :=

Win.ReadString{'

anl.Caption :=

Win.ReadString('

an3.Caption :=

Win.ReadString('

an4.Caption := .

Win.ReadString('

Win.Free;

yes := an2. Caption

end;

3: begin

Q',

A',

Wl' ,

W 2 \

W3',

Win := TIniFile.Create

Memol.Text :=

Win.ReadString('

an3.Caption :=

Win.ReadString('

an2.Caption :=

Win.ReadString('

anl.Caption :=

Win.ReadString('

an4.Caption :=

Win.ReadString('

Win.Free;

yes := an3.Caption

end;

4 : begin

Q \

A',

Wl',

W2' ,

W3' ,

Win := TIniFile.Create

Memol.Text :=

Win.ReadString('Q',

(dir2);

IntToStr(a),

IntToStr(a),

IntToStr(a)

IntToStr (a)

IntToStr(a)

(dir2);

IntToStr(a),

IntToStr(a),

IntToStr(a)

IntToStr (a)

IntToStr(a)

(dir2);

IntToStr(a),

Memol.Text);

an2.Caption);

, anl.Caption);

, апЗ.Caption);

, an4.Caption);

Memol.Text);

апЗ.Caption);

, an2.Caption);

, anl.Caption);

, an4.Caption);

Memol.Text);

Page 119: Delphi учимся на примерах

118 Тест

Листинг 13.1. Продолжение

an4.Caption : =Win.ReadString('A' , IntToStr(a), an4.Caption) ;

an2.Caption :=Win.ReadString('Wl', IntToStr(a), an2.Caption);

апЗ.Caption :=Win-.ReadString ( 'W2 ' , IntToStr (a), an3.Caption);

anl.Caption :=Win.ReadString('W3', IntToStr(a), anl.Caption);

Win.Free;yes := an4.Caption;

end;end;

end;

procedure TForml.start();begin

Randomize; //Включаем генератор случайных чиселfor i:=l to n do mass[i] := 0; //n = количеству вопросов{$1-} //отключаем контроль ошибок ввода/вывода//делаем все элементы видимыми для пользователяMemol.Visible := True;RadioGroupl.Visible := True;Labell.Visible := True;anl.Visible := True;an2.Visible :- True;an3.Visible := True;an4.Visible := True;pi.Visible := True;p2.Visible := False;p3.Visible := False;p4.Visible := False;p5 . Visible :•» False;balls := 0;Label2.Visible := False; //прячем результатыLabell.Caption := 'Первый вопрос:

1;

dir2 := 'C:\base.bsd'; //путь к расшифрованной базе//копируем зашифрованную базу на диск С:CopyFile(PChar(ss), PChar(dir2), True);//связываем переменную fl с зашифрованным ini-файломAssignFile(fl, ss);//связываем переменную f2 с файлом C:\base.bsdAssignFile(f2, dir2);Reset (fl); //открываем первый файл на чтениеRewrite(f2); //второй - на записьwhile not Eof(fl) do

Page 120: Delphi учимся на примерах

Полный исходный код модуля 119

Листинг 13.1. Продолжение

begin //пока не достигнут конец первого файлаRead(fl, cop); //считываем один символ из файласор := Chr(Ord(cop) xor 101); //расшифровываем символWrite(f2, cop); //записываем расшифрованный символ в файл

end;CloseFile(f1); //закрываем первый файлCloseFile(f2); //закрываем второй файл{$1+} //включаем контроль ошибок ввода/выводаWin := TIniFile.Create(dir2); //работаем с ini-файлом//считываем количество вопросов в базеss := Win.ReadString('num', 'num', ss);//преобразовываем строку в число и записываем значение в пn := StrToInt(ss);vopr := Random(4) + 1; //случайное число от 1 до 4vars(vopr); (передаем число процедуре vars, которая

сортирует варианты ответов}end;

procedure TForml.question_select();label ran; //метка ran для быстрого переходаbegin

Randomize;

ran:a := Random(n); //выбираем случайный вопрос из базы//проверяем: не задавали ли мы этот вопрос ранееfor i:=l to n doif mass[i] = a then goto ran;

for i:=l to n doif massfi] = 0 thenbegin

mass[i] := а; (записываем номер вопроса, чтобы незадавать его больше }

Break;end;

//сбрасываем флажки со всех вариантов ответаanl.Checked := False;an2.Checked := False;апЗ.Checked := False;an4.Checked := False;

end;

procedure TForml.verno();begin

if anl.Checked thenif yes = anl.Caption then balls := balls + 1;

if an2.Checked then

Page 121: Delphi учимся на примерах

120 Тест

Листинг 13.1. Продолжение

if yes = an2.Caption then balls : = balls + 1;

if an3.Checked then

if yes = an3.Caption then balls : = balls + 1;

if an4.Checked then

if yes = an4.Caption then balls := balls + 1;

end;

procedure TForml.N2Click(Sender: TObject);

begin

Randomize;

//начинаем обзор с текущего каталога

Openl.InitialDir := GetCurrentDir;

if not Openl.Execute

then ShowMessage('Вы не выбрали файл!1)

else begin

ss := Openl.FileName; //открываем выбранный файл

zz := ss; //запоминаем путь к базе

start(); //начинаем тест

end;

end;

procedure TForml.FormCreate(Sender: TObject};

begin

Randomize;

//получаем каталог, в котором находится наша программа

dir := GetCurrentDir;

ss : = dir + '\comp.ini'; //путь к базе вопросов

z z : = s s ;

start(); //начинаем тест

end;

procedure TForml.plClick(Sender: TObject);

begin

Labell.Caption := 'Второй вопрос:';

verno (); //принимаем вариант ответа

pi.Visible := False; //убираем первую панель

р2.Visible := True; //активизируем вторую панель

vopr := Random(4) + 1; //выбираем случайный вариант ответа

vars(vopr); //задаем вопрос

end;

procedure TForml.p2Click(Sender: TObject);

begin

Labell.Caption := 'Третий вопрос:';

Page 122: Delphi учимся на примерах

Полный исходный код модуля 121

Листинг 13.1. Продолжение

р2.Visible : =рЗ.Visible :=

False;True;

vopr := Random(4) 4 1;vars(vopr);

end;

procedure TFormlbegin

Labell.Caption

verno ();p3.Visible :=p4.Visible :=

.p3Click(Sender: TObject);

:= 'Четвертый вопрос: '•;

False;True;

vopr :- Random(4) + 1;vars(vopr);

end;

procedure TFormlbegin

Labell.Caption

verno();p4.Visible :=p5.Visible :=

.p4Click(Sender: TObject);

:= 'Пятый вопрос:';

False;True;

vopr := Random(4) + 1;vars(vopr);

end;

procedure TFormlbegin

.p5Click(Sender: TObject);

verno();//проверяем правильность ответа на последний вопрос//узнаем, сколько баллов набрал пользовательss : = IntToStrMemol.Visibleр5.Visible :=

(balls);:= False;False;

RadioGroupl.Visible : = False;Labell.Visibleanl.Visible :=an2.Visible :=an3.Visible :=an4.Visible :=Label2.VisibleLabel2.Align :

:= False;False;False;False;False;:= True; //показываем метку с результатом

= alClient; //растягиваем ее на всю форму//Отображаем процент правильных ответовLabel2.Caption

end;

:= 'Правильных ответов' +IntToStr(balls*(100 div 5))+'%';

Page 123: Delphi учимся на примерах

122 Тест

Листинг 13.1. Продолжение

procedure TForml.N4Click(Sender: TObject);begin

Halt;end;

procedure TForml.plMouseDown(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

beginpi.Bevellnner := bvLowered;pi.BevelOuter := bvRaised;

end;

procedure TForml.plMouseUp(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

beginpi.Bevellnner := bvRaised;pi.BevelOuter := bvLowered;

end;

procedure TForml.p2MouseDown(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

beginp2.Bevellnner := bvLowered;p2.BevelOuter := bvRaised;

end;

procedure TForml.p2MouseUp(Sender: TObject; 'Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

beginp2.Bevellnner := bvRaised;p2.BevelOuter := bvLowered;

end;

procedure TForml.p3MouseDown(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y- Integer);

beginp3.Bevellnner := bvLowered;p3.BevelOuter := bvRaised;

end;

procedure TForml.p3MouseUp(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

beginp3.Bevellnner := bvRaised;p3.BevelOuter := bvLowered;

Page 124: Delphi учимся на примерах

Полный исходный код модуля 123

Листинг 13.1. Окончание

end;

procedure TForml.p4MouseUp(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer)

begin

p4.Bevellnner : = bvRaised;

p4.BevelOuter := bvLowered;

end;

procedure TForml.p4MouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer)

begin

p4.Bevellnner := bvLowered;

p4.BevelOuter := bvRaised;

end;

procedure TForml.p5MouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

p5.Bevellnner := bvLowered;

p5.BevelOuter := bvRaised;

end;

procedure TForml.pbMouseUp(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer)

begin

p5.Bevellnner := bvRaised;

p5.BevelOuter := bvLowered;

end;

procedure TForml.NIClick(Sender: TObject);

begin

Randomize;

s s : = z z ;

start () ;

end;

procedure TForml.FormDestroy(Sender: TObject);

begin

DeleteFile('c:\base.bsd');

end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r _ 1 3 .

Page 125: Delphi учимся на примерах

124 Генератор шуток

Глава 14

Генератор шуток

Постановка задачиРазработать программу, которая будет работать незаметно для

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

Разработка формыСоздайте новый проект Delphi. Для того чтобы выполнять периоди-

ческие действия, нам понадобится компонент Timer категории System.Программа будет выполнять каждую минуту случайно выбранную шут-ку. Для того чтобы таймер срабатывал каждую минуту, необходимоприсвоить свойству I n t e r v a l значение 60000. Больше никакихсвойств ни для формы, ни для таймера изменять не нужно.

Разработка программного кодаПервое, что нужно сделать для шуточной программы, — скрыть ее

от глаз пользователя. Для этого достаточно создать обработчик событияформы On Paint и добавить в него следующий код:procedure TForml.FormPaint(Sender: TObject)begin

Forml.Hide; //прячем формуend;

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

Еще одно важное действие для нашей программы — реализация ав-тозагрузки вместе с запуском ОС. Для этого создайте обработчик собы-тия главной формы OnCreate и добавьте в него следующий код:procedure TForml.FormCreate(Sender: TObject);

Page 126: Delphi учимся на примерах

Разработка программного кода 125

reg: TRegistry; //переменная для работы с реестромpath: string; //содержит путь к нашей программе

beginRandomize; //генератор случайных чисел//узнаем путь к программе и ее имяpath := Application.EXEname;reg := TRegistry.Create; //открываем реестр//ветка текущего пользователяreg.RootKey := HKEY_CURRENT_USER;

//открываем раздел автозагрузкиif reg.OpenKey('\Software\Microsoft\Windows\' +

1CurrentVersion\Run', True)

then begin

//записываем ссылку на нашу программу в автозагрузкуreg.WriteString('Joker', path);reg.CloseKey; //закрываем реестрreg.Free; //освобождаем память

end;end;

Чтобы это все работало, необходимо добавить в раздел uses ссылкуна модуль Registry. Теперь все готово для создания программных шу-ток. Сначала o6jb£Bj™j^ej^)6^^ __var

Forml: TForml;//для отключения мыши и клавиатурыDummy: integer = 0;OldKbHook: HHook = 0;//для снятия копии экранаВМР1: Graphics.TBitmap;DC1: HDC;Imagel: TImage;// для поиска случайного рисункаfn:TSearchRec;Finds: integer;

i: integer;endval: integer;err_str: string; //вывод ошибкиtm: TSystemTime; //изменение времениreg: TRegistry; //для работы с реестромJokeNum: shortint; //номер шутки, которую следует выполнитьcurs: TRect; //координаты прямоугольника

Все шутки будут описаны в обработчике события таймера OnTimer.Добавьтевэто^procedure TForml.TimerlTimer(Sender: TObject);begin

Page 127: Delphi учимся на примерах

126 Генератор шуток

JokeNum := Random(10) + 1 ; //Выбираем случайный номер шуткиcase JokeNum of //выполняем шутку

1:

2:

3:

4:

5:

6:

7:

8:

9:

10:

end;

end;

begin//код

end;begin

//кодend;

begin

//кодend;begin

//кодend;

begin

//кодend;

begin

//кодend;begin

//кодend;begin

//кодend;begin

//кодend;begin

//кодend;

первой шутки

второй шутки

третьей шутки

четвертой шутки

пятой шутки

шестой шутки

седьмой шутки

восьмой шутки

девятой шутки

десятой шутки

Это шаблон для генератора шуток. Здесь выбирается случайноечисло от 1 до 10, которое будет определять, какую из шуток выполнитьна этой минуте. Далее будут представлены фрагменты кода, выпол-няющие определенные действия, которые следует вставлять вместокомментария в соответствующую ветку конструкции case.

Шутка №1 — ограничение диапазона движения мыши

Итак, первая шутка заключается в наложении ограничения на диа-пазон движения мыши:

оГ Screen . Width div 2, Screen. Height) ;

Page 128: Delphi учимся на примерах

Разработка программного кода 127

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

Шутка №2 — отключение кнопок мыши

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

function KbHook(code: Integer; wparam: Word;lparam: Longlnt): Longlnt; stdcall;

beginif code < 0 thenResult := CallNextHookEx(oldKbHook, code, wparam, lparam)

elseResult := 1;

end;

После этого напишите код для второй шутки:SystemParametersInfo(SPI_SETFASTTASKSWITCH, I, @Dummy, 0);SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, @Пшпту, 0) ;OldKbHook:=SetWindowsHookEx(WH mouse, OKbHook, HInstance, 0);

После этого ни одна из кнопок мыши функционировать не будет.

Шутка №3 — отключение клавиатуры

Используя функцию для отключения мыши, можно написать код

SystemParametersInfo(SPI_SETFASTTASKSWITCH, I, @Dummy, 0);SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, SDummy, 0);OldKbHook:=SetWindowsHookEx(WH_KEYBOARD,SKbHook,HInstance,0);

t пищ и 11 щи пнищи щи i и mil iiiiiiinnniiiiiiiiiiiiiiiiiniiiii и • •••IHMIIIIIIHIIHIMIHUI n I inn «IIHIII I n r IIIIHTII • •n11 —•• ••*»!>•» 1141 IIII mm ' " и и ill "ill i in i nmni 11 n i м i i и in i мм i m i I i in I i i ft

Здесь вызывается та же функция, только вместо параметраWH_MOUSE ей передается WH_KEYBOARD. После этого клавиши на клавиа-туре перестанут функционировать.

Шутка №4 — очистка буфера обмена

Четвертая шутка будет очищать буфер обмена и помещать тудасобственный текст. Ее код:ClipBoard.Open; //открываем буфер обменаClipBoard.Clear; //очищаем буфер обмена

//Помещаем в буфер обмена свой текст}Clipboard.asText := 'Буфер обмена временно не работает!

Page 129: Delphi учимся на примерах

128 Генератор шуток

j ClipBoard.Close; //закрываем буфер обмена

Для работы с буфером обмена необходимо добавить в раздел useссылку на модуль c l i p b r d .

Шутка №5 — назначение фона для Рабочего стола

Пятая шутка будет делать копию экрана, сохранять этот рисунок, азатем назначать его в качестве фона для Рабочего стола. Вначале в раз-деле implementation напишем процедуру SetWallpaper, которая бу-

procedure SetWallpaper(sWallpaperBMPPath: String;bTile: boolean );

beginreg := TRegistry.Create;reg.RootKey := hkey_current_user;if reg.OpenKey('Control Panel\Desktop', True)then reg.WriteString('Wallpaper', sWallpaperBMPPath); {ключ

содержащий путь к bmp-файлу }//растянуть рисунок на весь экранreg.WriteString('TileWallpaper', Ч

1 );

with reg dobegin

WriteString('Wallpaper', sWallpaperBMPPath );

if bTile thenbeginWriteString('TileWallpaper', '1' );

endelse begin

WriteString('TileWallpaper', '0' ) ;end;

end;reg.Free;SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, Nil,

SPIF_SENDWININICHANGE );end;

Информацию о фоновом рисунке Рабочего стола можно найтив реестре в ветке HKEY_CURRENT_USER по пути \Control Panel\Desktop. Параметр, содержащий название рисунка, называется wal l-paper. То есть, для того чтобы сменить "обои" нам необходимо изме-нить значение параметра wallpaper и оповестить систему о том, чтобыли внесены изменения в реестр. Последняя строка самая важная —она обновляет системные настройки.

Page 130: Delphi учимся на примерах

Разработка программного кода 129

Функция SystemParametersInfo имеет следующие параметры:• действие, которое необходимо выполнить (в нашем случае

SPi_SETDESKWALLPAPER — установка обоев);• зависит от значения первого параметра;• в нашем случае — путь к файлу с рисунком;• в последнем параметре указывается, что необходимо сделать по-

сле выполнения всех действий. В данном случае мы должны об-новить настройки системы — для этого выбираемSPIFSENDWININICHANGE.

^ в и д :

ВМР1 := Graphics.TBitmap.Create;//задаем размеры рисунка такие же, как размеры экранаВМР1.Height := Screen.Height;ВМР1.Width := Screen.Width;DC1 := GetDC(O);//Делаем копию экранаBitBlt(BMPl.Canvas.Handle, 0, 0, Screen.Width,

Screen.Height, DC1, 0, 0, SRCCOPY);Forml.Visible := True; //восстанавливаем окно нашей программыImagel := TImage.Create(nil);BMP1.IgnorePalette := True;Imagel.Picture.Assign(BMP1);BMP1.SaveToFile('с:\1.bmp'); //сохраняем снимок в файл l.bmpSetWallpaper('с:\1.bmp', False ); //назначаем снимок, как фонRepaint; //обновляем

Здесь мы делаем копию экрана, сохраняем ее в файл и, вызываяпроцедуру SetWallPaper, назначаем в качестве фона Рабочего стола.

Шутка №6 — выбор фона случайным образом

Раз уж мы написали процедуру, которая устанавливает фоновыйрисунок, почему бы не использовать ее в нашей следующей шутке?Шестая шутка будет заключаться в том, чтобы выбрать случайным об-разом рисунок из каталога Windows и сделать его фоновым:endval := Random(10) + 5; //для случайности выбора рисунка

//ищем все файлы с расширением *.bmp в каталоге Windows

Finds := FindFirst('С:\Windows\*.bmp1, faAnyFile, f n ) ;

Finds := Random(2); //случайное число, 0 или 1

//если выпала 1, то устанавливаем первый попавшийся рисунок

if Finds = 1 then SetWallpaper(fn.Name, False ) ;

if Finds = 0 then

begin //иначе...

for i:=1 to endval do

9 — 5-1212

Page 131: Delphi учимся на примерах

130 Генератор шуток

beginFinds := FindNext(fn); // ...ищем другие рисунки//выбираем любой другой рисунок и делаем его фоновымif i = endval - 3 then SetWallpaper(fn.Name, False);

end;end;FindClose(fn); //завершаем поиск

Здесь мы перебираем все рисунки в каталоге Windows и случайнымобразом выбираем один из них в качестве фонового. Затем мы устанав-ливаем фон с помощью ранее созданной процедуры SetWallpaper.

Шутка №7 — выключение монитора

Седьмая шутка будет выключать монитор. Для этого достаточнонаписать одну строку кода:SendMessage(Application.Handle, WM_SYSCOMMAND,

SC MONITORPOWER, 1);

Шутка №8 — сообщение об ошибке, содержащее "мусор"

Восьмая шутка будет выводить сообщение об ошибке, но не про-стое, а содержащее огромное количество случайных чисел. Код этойшутки|for i:=l to 200 dobegin

case i of//после каждого 25-го числа - перенос на новую строку25,50,75,100,125,150,175,199: err_str := err_str+#13#10;

end;

//текст "ошибки"err_str := err_str + IntToStr(Random(99999));

end;MessageDlg(err str, mtError, [mbOk], 0); //выводим сообщение

В цикле от 1 до 200 выбирается случайное число от 0 до 99999. Всечисла преобразовываются к символьному виду и добавляются к строко-вой переменной e r r s t r . На каждом 25-м числе происходит переносстроки. В результате выдается примерно такое сообщение об "ошибке"как на рис. 14.1.

Page 132: Delphi учимся на примерах

Полный исходный код модуля 131

79090611493386922201256626?50l2lS14143S8702680664lS21lS347882807?36S%84349391373487S4l9431822383?;:.:4 " J i. м;Л4Й4Ь243827664873856402906ЭШ196184 3087453218447?6S363737693373022673S610996S49882003454835%762614?416t5i43c.S025o54S66209S5080S6S0831%0898S6959W71629239e5460523«5977727960033932914S919!02039630832649U994092721096109?S87437392B842;;08892842a7582Q745823307633955726149399599688364066373152439022040603704767271849852356796146990262965438631474192769091141347254436372179674861069S287696742592463347293256S3738??1S8246?65601543234 2931619914048214765744 7961583233193107556578227512393! 139289978335279254460045148187601648692205292211267641364207620730920898166832992798583694591925067672593287771182234836233035604836799035368907810573112715U46342972S031316580022524839f206S38ie91213217892714563818S905931?ei 8863517479129226951563027380467309SU45S64I • • : •• '

Рис. 14.1. Сообщение об "ошибке"

Шутка №9 — открытие браузера Internet Explorer

В девятой шутке мы будем открывать несколько (от 5 до 15) оконбраузера Internet Explorer с попыткой зайти на сайт wwv;. h e e l . nm. ru.Код этой шутки:for i:=l to Random(10) + 5 do //случайное число от 5 до 15

ShellExecute(0, 'open','C:\Program Files\lnternet Explorer\' +1IEXPLOKE.EXE', 'www.heel.nm.ru

1, 0,

SW MAXIMIZE);

Чтобы использовать функцию ShellExecute, необходимо доба-вить в раздел uses ссылку на модуль ShellApi.

Шутка №10 — сброс системной даты/времени

Последняя, десятая шутка будет устанавливать текущую дату01.01.2000, и изменять текущее время на 00:00:01. Код этой шутки:GetLocalTime(tm); //узнаем текущую дату и времяtm.wYear := 2000; //устанавливаем год

tm.wMonth := 01; //месяцtm.wDay := 01; //деньtm.wHour := 0; //часыtm.wMinute := 0; //минутыtm.wSecond := 1; //секунды

I tm.wMilliseconds := 0; //мсI SetLocalTime(tin); //устанавливаем новую дату и время1_

Полный исходный код модуляПолный код программного модуля генератора шуток представлен

в листинге 14.1.

Page 133: Delphi учимся на примерах

132 Генератор шуток

Листинг 14.1, Программный модуль генератора шуток

unit Unitl;

interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, ExtCtrls, Registry, clipbrd,ShellApi;

typeTForml = class(TForm)

Timerl: TTimer;procedure TimerlTimer(Sender: TObject);procedure FormPaint(Sender: TObject);procedure FormCreate(Sender: TObject);

private{ Private declarations }

public

{ Public declarations }end;

varForml: TForml;//для отключения мыши и клавиатурыDummy: integer • 0;OldKbHook: HHook = 0;//для снятия копии экрана

ВМР1: Graphics.TBitmap;'DC1: HDC;Imagel: TImage;// для поиска случайного рисункаfn:TSearchRec;Finds: integer;i: integer;endval: integer;err_str: string; //вывод ошибки

tm: TsystemTime; //изменение времениreg: Tregistry; //для работы с реестром

JokeNum: shortint; //номер прикола, который нужно выполнитьcurs: TRect; //координаты прямоугольника

implementation

procedure SetWallpaper(sWallpaperBMPPath: String;bTile: boolean );

Page 134: Delphi учимся на примерах

Полный исходный код модуля 133

Листинг 14.1. Продолжение

beginreg := TRegistry.Create;reg.RootKey :- hkey_current_user;if reg.OpenKey('Control Panel\Desktop', True)then reg.WriteString('Wallpaper', sWallpaperBMPPath); {ключ

содержащий путь к bmp-файлу }//растянуть рисунок на весь экранreg.WriteString('TileWallpaper' , '1' ) ;with reg dobegin

WriteString('Wallpaper', sWallpaperBMPPath );

if bTile then

beginWriteString('TileWallpaper', '1' );

endelse begin

WriteString('TileWallpaper', '0' );end ;

end;

reg.Free;SystemParametersInfо(SPI_SETDESKWALLPAPER, 0, Nil,

SPIF_SENDWININICHANGE );end;

function KbHook(code: Integer; wparam: Word;

lparam: Longlnt): Longlnt; stdcall;

begin

if code < 0 then

Result := CallNextHookEx(oldKbHook, code, wparam, lparam)

else

Result := 1 ;

end;

{$R *.dfm}

procedure TForml.TimerlTimer(Sender: TObject);var

JokeNum: shortint;curs: TRect;

begin

JokeNum := Random(10) + 1;case JokeNum of

1: begin //Уменьшить диапазон движения мыши

curs := Rect(0,0,Screen.Width div 2,Screen.Height);ClipCursor(Scurs);

Page 135: Delphi учимся на примерах

134 Генератор шуток

Листинг 14.1. Продолжение

end;begin //Отключить мышь

SystemParametersInfo(SPI_SETFASTTASKSWITOH, 1,@ Dummy, 0) ;

SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1,@Dummy, 0);

OldKbHook := SetWindowsHookEx(WH_mouse, @KbHook,HInstance, 0);

end;begin //отключить клавиатуру

SystemParametersInfo(SPI_SETFASTTASKSWITCH, 1,@Dummy, 0);

SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1,@Dummy, 0);

OldKbHook := SetWindowsHookEx(WH_KEYBOARD, @KbHook,HInstance, 0);

end;begin //Очистить буфер обмена

ClipBoard.Open; //открываем буфер обменаClipBoard.Clear; //очищаем буфер обмена//Помещаем в буфер обмена свой текстClipboard.asText :=

'Буфер обмена временно не работает!';ClipBoard.Close; //закрываем буфер обмена

end;begin //Сделать копию экрана и назначить ее фоном

ВМР1 := Graphics.TBitmap.Create;//задаем размеры рисунка как размеры экранаВМР1.Height := Screen.Height;ВМР1.Width := Screen.Width;DC1 := GetDC(O);//Делаем копию экранаBitBlt(BMP1.Canvas.Handle, 0, 0, Screen.Width,

Screen.Height, DC1, 0, 0, SRCCOPY);

//восстанавливаем окно нашей программыForml.Visible := True;

Imagel := TImage.Create(nil) ;BMP1.IgnorePalette := True;Imagel.Picture.Assign(BMPl);//сохраняем копию экрана в файл l.bmp на диске С:\BMPl.SaveToFile('с:\l.bmp');//установим сделанный снимок как фонSetWallpaper('с:\1.bmp', False);Repaint; //обновляем

end;

Page 136: Delphi учимся на примерах

Полный исходный код модуля 135

Листинг 14.1. Продолжениеj II.. I I •'"• » I

6: begin //Найти случайный рисунок и сделать его фоновымendval := Random(lO) + 5; //случайный выбор рисунка//ищем все файлы *.bmp в каталоге WindowsFinds := FindFirst('С:\Windows\*.bmp',faAnyFile,fn);Finds := Random(2); //случайное число, 0 или 1//если 1, то устанавливаем первый попавшийся рисунокif Finds = 1 then SetWallpaper(fn.Name, False);if finds=0 thenbegin //иначе...

for i:=l to endval dobegin

Finds := FindNext(fn); // ...ищем другие рисунки//выбираем любой другой рисунок и делаем его фоновым

if i=endval-3 then SetWallpaper(fn.Name, False);end;

end;

FindClose(fn); //завершаем поискend;

7: begin //Выключить монитор

SendMessage(Application.Handle, WM__SYSCOMMAND,SC_MONITORPOWER, 1);

end;

8: begin //Сообщение об "ошибке"for i:=l to 200 dobegin

//после каждого 25-го числа - перенос строкиcase i of

25,50,75,100,125,150,175,199: err_str := err_str + #13#10;

end;//текст "ошибки"err_str := err_str + IntToStr(random!99999));

end;MessageDlg (err_str, mtError, "• [mbOk] , 0); //сообщение

end;

9: begin //Запуск Internet Explorerfor i:=l to Random(lO) + 5 doShellExecute(0, 'open',

'C:\Program FilesMnternet Explorer\' +1IEXPLORE.EXE', 'www.heel.nm.ru',0, SW_MAXIMIZE) ;

end;10: begin //Перевести время

GetLocalTime(tm); //узнаем текущую дату и времяtm.wYear := 2000; //устанавливаем годtm.wMonth := 01; //месяц

Page 137: Delphi учимся на примерах

136 Генератор шуток

Листинг 14.1. Окончание

tm.wDay := 01; //деньtm.wHour : = 0; //часыtm.wMinute : = 0; //минутыtm.wSecond := 1; //секундыtm.wMilliseconds : = 0; //мсSetLocalTime(tm); //устанавливаем новую дату и время

end;end;

; end;

procedure TForml.FormPaint(Sender: TObject);• begin; Forml.hide; //прячем форму

end;

procedure TForml.FormCreate(Sender: TObject);var

reg: TRegistry; //переменная для работы с реестромpath: string; //содержит путь к нашей программе

begin

Randomize; //генератор случайных чисел//узнаем путь к программе и ее имяpath : = Application.EXEname;

reg := TRegistry.Create; //открываем реестр//ветка текущего пользователяreg.RootKey : = HKEY_CURRENT_USER;//открываем раздел автозагрузки

if reg.OpenKey('\Software\Microsoft\Windows\' +'CurrentVersion\Run', True)

then begin

//записываем ссылку на нашу программу в автозагрузкуreg.WriteString ('Joker', path);reg.CloseKey; //закрываем реестрreg.Free; //освобождаем память

end;end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке Chapter__14.

Page 138: Delphi учимся на примерах

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

Глава 15

Отправка сообщении в локальной

Постановка задачиРазработать программу, которая будет предоставлять интерфейс для

использования стандартной для Win2000/XP команды передачи сооб-щений net send. Дать возможность указать пользователю адрес полу-чателя, текст сообщения и количество отправляемых сообщений. Такжепредусмотреть возможность установки блокировки на получение сооб-щений от других компьютеров.

Разработка формыСоздайте новый проект Delphi. Измените заголовок формы (свойст-

во Caption) на Net Sender. Разместите вдоль левого края формы одиннад другим три компонента Label категории Standard и присвойте ихсвойству Caption значения IP-адрес:, Сообщение: И Количество:.

Рядом с каждой из меток разместите по компоненту Edit категорииStandard. Самый верхний назовите ip (свойство Name), а свойству Textприсвойте значение 192 .168 . О . 1.; среднее поле назовите txt, а свой-ству Text присвойте какой-либо текст сообщения по умолчанию; самоенижнее поле назовите how, а свойству Text присвойте значение 1.

Под перечисленными компонентами разместите компонент Check-box категории Standard. Присвойте ему имя secure, свойству Captionприсвойте значение Отключить прием сообщений, а свойствуChecked — значение True.

В самом низу формы разместите кнопку (компонент Button кате-гории Standard), присвоив ее свойству Caption значение Send. Такженам понадобится таймер (компонент Timer категории System), для ко-торого свойству I n t e r v a l следует присвоить значение 10.

Полученная форма должна соответствовать рис. 15.1.

Page 139: Delphi учимся на примерах

138 Отправка сообщений в локальной сети

ШNet sender

IP-адрес:; 3i92.168О

Сообщение: jSmS

Количество:; 1W Отключить прием сообщений

Send

Рис. 15.1. Форма для программы отправки сообщений в локальной сети

Разработка программного кодаПрежде всего напишем собственную процедуру bomb, которая бу-

дет считывать все настройки и отправлять сообщение. Объявите этупроцедуру K^^aKpjbmiHj4JieH класса формы: __ _ _] type

TForml = class(TForm)

private{ Private declarations }procedure bomb();

public{ Public declarations }

i end;

п е £ 5 м е н н а я i

т и п а integer:

I varI Forml: TForml;

i: integer;

Теперь создадим реализацию процедуры bomb в разделе implemen-tation: ...

;. : ,,..

procedure TForml.bomb();

begin

//проверяем, не пустое ли текстовое сообщениеif txt.Text = '' then txt.Text := '!';

//если количество не указано, то отправляем одно сообщениеif how.Text = " then how.Text := Ч

1;

if ip.Text = '• then ip.Text := 427.0.0.1'; {если ip-адресне указан, то отправляем на локальный компьютер}

//отправляем указанное количество сообщенийfor i:=l to StrToInt(how.Text) do

Page 140: Delphi учимся на примерах

Разработка программного кода 139

WinExec(PChar('net send ' + ip.Text + '"' + txt.Text +

'"') , 0) ; //отправка сообщенияI end; |

В этой процедуре выполняется проверка: все ли необходимые полязаполнены. Если нет текста сообщения, то устанавливаем знак "!"; еслине указан IP-адрес, то отправляем сообщение на локальный компьютер садресом 127.0.0.1; если не указано количество сообщений, то отправля-ем одно сообщение. Сообщения отправляются с помощью стандартнойкоманды net send, которая имеет следующий синтаксис:

net send ip-адрес сообщение.

^ ^

(procedure TForml.TimerITimer(Sender: TObject);var

h: HWND; //хранит идентификатор окна| begin

if not secure.Checked then //если флажок не установленTimerl.Enabled := False; //отключаем мониторинг

if secure.Checked then //если флажок установленbegin

//ищем окна с сообщениямиh := FindWindow(nil, 'Служба сообщений ' ) ;//закрываем все найденные окнаif h О О then PostMessage(h, WM_QUIT, 0, 0);

end;

end;

Если установлен флажок Отключить прием сообщений, то мы начи-наем мониторинг окон, заголовок которых говорит о том, что это — со-общение, и закрываем все найденные окна. Если флажок не установлен,то мониторинг отключается.

Для того чтобы можно было переключаться между этими двумя ре-жимами, необходимсисоздать 2бр_аботчик события s e c u r e . OnClick:procedure TForml.secureClick(Sender: TObject);begin

if secure.Checked then //если флажок установлен...Timerl.Enabled := True; II.. .включаем мониторинг

end;

При нажатии кнопки Send мы будем просто вызывать процедуруbomb:procedure TForml.ButtonlClick(Sender: TObject);begin

bomb;

Page 141: Delphi учимся на примерах

140 Отправка сообщений в локальной сети

end;

Для того чтобы облегчить пользователю жизнь, сделаем так, чтобыотправка сообщения осуществлялась также по нажатии клавиши<Enter> в любом текстовом поле ввода. Для этого необходимо создатьобработчик события OnKeyPress для каждого из полей. Код этого об-работчика для поля ip, который затем можно назначить полям t x t иhow: _| procedure TForml.ipKeyPress(Sender: TObject; var Key: Char);! begin

if key = #13 then //если нажата клавиша <Enter>bomb; //отправка сообщения

• end;

Полный исходный код модуляПолный код модуля программы отправки сообщений по локальной

сети представлен в листинге 15.1.

Листинг 15.1. Модуль программы отправки сообщений по локальной сети

unit Unitl;

interface

uses

>

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

typeTForml - class(TForm)Buttonl: TButton;ip: TEdit;Label1: TLabel;Label2: TLabel;txt: TEdit;Label3: TLabel;how: TEdit;secure: TCheckBox;Timerl: TTimer;procedure TimerlTimer(Sender:procedure secureClick(Sender:procedure ipKeyPress(Sender:procedure txtKeyPress(Sender:procedure howKeyPress(Sender:procedure ButtonlClick(Sender

private

1j

|

1

i

1TObject);TObject);

TObject; var Key: Char);TObject; var Key: Char);TObject; var Key: Char);: TObject);

Page 142: Delphi учимся на примерах

Полный исходный код модуля 141

Листинг 15.1. Продолжение

{ Private declarations }procedure bomb();

publicf Public declarations }

end;

varForml: TForml;i: integer;

j implementation

I ($R *.dfm}

procedure TForml.bomb();begin

//проверяем, не пустое ли текстовое сообщениеif txt.Text = '' then txt.Text := '!';//если количество не указано, то отправляем одно сообщениеif how.Text = '' then how.Text := '1';if ip.Text = '' then ip.Text := '127.0.0.1'; {если ip-адрес

не указан, то отправляем на локальный компьютер}//отправляем указанное количество сообщенийfor i:=l to StrToInt(how.Text) doWinExec (PChar('net send ' + ip.Text + '"' + txt.Text +

' " ' ) , 0); //отправка сообщения! end;{

! procedure TForml.TimerlTimer(Sender: TObject);var

h: HWND; //хранит идентификатор окнаbegin

if not secure.Checked then //если флажок не установленTimerl.Enabled := False; //отключаем мониторинг

if secure.Checked then //если флажок установленbegin

//ищем окна с сообщениямиh := FindWindow(nil, 'Служба сообщений ' ) ;//закрываем все найденные окнаif h о 0 then PostMessage(h, WM_QUIT, 0, 0);

end;end;

procedure TForml.secureClick(Sender: TObject);begin

Page 143: Delphi учимся на примерах

142 Отправка сообщений в локальной сети

Листинг 15.1. Окончание

secure.CheckedTimerl.Enabled := True; //...включаем мониторинг

if secure.Checked then //если флажок установлен...

end;

procedure TForml.ipKeyPress(Sender: TObject; var Key: Char);begin

if key = #13 then //если нажата клавиша <Enter>bomb; //отправка сообщения

end;

procedure TForml.ButtonlClick(Sender: TObject);begin

bomb;end;

I end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 15.

Page 144: Delphi учимся на примерах

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

Глава 16

Удаленное управление указателеммыши

Постановка задачиРазработать программу, которая в точности повторяет на одном

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

На самом деле нам придется разработать две программы: первая(назовем ее "Клиент") будет получать координаты указателя на одномкомпьютере и отправлять их второй программе (назовем ее "Сервер"),которая будет принимать и изменять текущие координаты указателя наприсланные клиентом. Данный тип связи называется "клиент-сервер" идля его использования у нас есть все необходимые компоненты на стан-дартной палитре компонентов Delphi. У "клиента" будет форма с на-стройками, а "сервер" будет работать незаметно для пользователя. Сна-чала разработаем клиентскую программу.

Разработка клиентской программы

Разработка формы

Создайте новый проект Delphi. Присвойте свойству Caption фор-мы заголовок Remote Mouse. Разместите на форме компонент Labelкатегории Standard и присвойте его свойству Caption значение Port.Справа от эгой метки разместите компонент Edit категории Standard.Назовите его p o r t (свойство Name), а свойству Text присвойте значе-ние 2801.

Ниже разместите еще один компонент Label, присвоив его свойст-ву Caption значение IP. Справа от него разместите компонент Edit сименем ip и текстом 127 . 0 . 0 . 1 .

Page 145: Delphi учимся на примерах

144 Удаленное управление указателем мыши

В самом низу формы разместите две кнопки (компоненты Buttonкатегории Standard), присвоив их свойству Caption значения Connectи Disconnect. Также нам понадобится компонент Timer категорииSystem. В свойствах таймера следует изменить значение свойства En-abled на False, а свойства I n t e r v a l — на 500 (что соответствует по-ловине секунды).

Разместите на форме самый важный компонент нашей програм-мы — Cl ientSocket категории Internet — и присвойте ему имя C l i e n t(свойство Name). Остальные свойства этого компоненты мы будем из-менять в самой программе.

Полученная форма должна соответствовать рис. 16.1.

Connect Disconnect

Рис. 16.1. Форма клиентской программы для удаленного управления указателем

Разработка программного кода

По нажатию кнопки Connect должны считываться все настройки ис_сервером: __

procedure TForml.ButtonlClick(Sender: TObject);begin

Client.Port := StrToInt(port.Text); //считываем портClient.Address := ip.Text; //считываем ip-адрес сервераClient.Active := True; //соединяемсяTimerl.Enabled := True; //включаем таймер

end ;

Сначала мы считываем все необходимые настройки, а затем пред-принимаем попытку соединиться с сервером. Если все нормально, товключаем таймер, по которому будут передаваться координаты указате-ля мыши.

Обработаем нажатие кнопки Disconnect: __i procedure TForml.Button2Click(Sender: TObject);I begin

Timerl.Enabled := False; //выключаем таймер

Page 146: Delphi учимся на примерах

Разработка клиентской программы 145

Client.Close; //закрываем соединениеClient.Active := False; //отключаемся от сервера

end;

При нажатии кнопки Disconnect мы перестаем передавать координа-ты указателя на сервер и отсоединяемся от него.

Для того чтобы на сервере не возникало ошибок при аварийном вы-ключении клиента, создайте обработчик события формы OnDestroy идобавьте в него следующий код:• procedure TForml.FormDestroy(Sender: TObject);; begin

Client.Close; //закрываем соединениеClient.Active := False; //отключаемся от сервера

end; !

При аварийном завершении программы закрывается соединение ивыполняется отключение от сервера.

Для уведомления пользователя об успешном соединении с серверомсоздайте обработчик события c l i e n t . OnConnect:procedure TForml.ClientConnect(Sender: TObject;

Socket: TCustomWinSocket);begin

ShowMessage('Connected!'); //показать сообщениеend;

Для реализации аналогичного действия при отсоединении от серве-а, следует создать обработчик события OnPiaconnect:procedure TForml.ClientDisconnect(Sender: TObject;

Socket:' TCustomWinSocket);begin

ShowMessage('Disconnected!'); //сообщение при отсоединенииend;

; OnTimer для компонента Timer:

procedure TForml.TimerITimer(Sender: TObject);var

cur: TPoint; //хранит координаты указателя мышиbegin

GetCursorPos(cur); //узнаем координаты указателя мыши//отправляем данные на серверClient.Socket.SendText(IntToStr(cur.X) + '_' +

IntToStr(cur.Y));

end;

Каждые полсекунды мы будем получать координаты указателя мы-ши и отправлять их на сервер. Программа-клиент полностью готова.Теперь разработаем программу-сервер.10 — 5-1212

Page 147: Delphi учимся на примерах

146 Удаленное управление указателем мыши

Разработка серверной программыСоздайте новый проект Delphi. Разместите на форме главный ком-

понент программы — ServerSocket категории Internet и измените зна-чение его свойства Port на 28 01.

Первым делом, обеспечим нашей форме невидимость. Создайте об-'аботчик co6j£THflj|)ojpj^^procedure TForml.FormPaint(Sender: TObject);begin

Forml.Hide;end;

Для того чтобы активизировать сервер при запуске программы, не-обходимо обработать событие формы OnCreate:procedure TForml.FormCreate(Sender: TObject);begin

ServerSocketl.Active := True; //активизировать серверend;

Для того чтобы при выходе из программы сервер отключался, необ-ходимо обработать событие формы OnDestroy:procedure TForml.FormDestroy(Sender: TObject);begin

ServerSocketl.Active := False; //отключаем серверend;

Теперь осталось только обработать событие OnClientRead компо-нента ServerSocket. Это событие будет происходить каждый раз, ко-гда будет поступать команда от клиента. Код обработчика этого собы-тия имеет следующий вид:procedure TForml.ServerSocketlClientRead(Sender: TObject;

Socket: TCustomWinSocket);I var

str, x, y: string; //полученный текст и координаты//указателя по X и по У

i, j: integer; //счетчики цикловbegin

//обнуляем координаты курсорах : = ' ' ;

Y : =str := Socket.ReceiveText; //полученный от клиента текстfor i:=l to Length(str) do

begin

if str[i] <> '_' then x := x + str[i]; //координаты по хif str[i] = '_' then Break; //разделитель между

Page 148: Delphi учимся на примерах

Полный исходный код модулей 147

//координатами указателяend;

for j:=i+l to Length(str) do у:=y+str[j]; //координаты по у//устанавливаем новые координаты указателяSetCursorPos(StrToInt(x) , StrToInt (у)) ;

end;

При получении текста мы считываем в отдельные переменные зна-чение координат указателя по X и по Y. Затем изменяем координаты нате, которые только что получили от клиента.

Теперь программа полностью готова, и для того чтобы протестиро-вать ее, необходимо иметь хотя бы два компьютера, объединенныев локальную сеть или подключенные к Internet.

Полный исходный код модулейПолный код модуля серверной программы представлен

в листинге 16.1.

Листинг 16.1. Модуль серверной программы

unit Unitl;

interface

Windows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, ScktComp;

typeTForml = class(TForm)

ServerSocketl: TServerSocket;procedure FormDestroy(Sender: TObject);procedure FormCreate(Sender: TObject);procedure ServerSocketlClientRead(Sender: TObject;

Socket: TCustomWinSocket);procedure FormPaint(Sender: TObject);

private

{ Private declarations }public

{ Public declarations }end;

varForml: TForml;

• implementation

10*

Page 149: Delphi учимся на примерах

148 Удаленное управление указателем мыши

Листинг 16.1. Окончание

j" {$R * . dfm}

procedure TForml.FormDestroy(Sender: TObject);j begin

ServerSocketl.Active := False; //закрыть соединение| end;

{procedure TForml.FormCreate(Sender: TObject);! begin

ServerSocketl.Active := True; //активизировать серверend;

procedure TForml.ServerSocketlClientRead(Sender: TObject;Socket: TCustomWinSocket);

varstr, x, y: string; //полученный текст и координаты

//указателя по X и по Yi, j: integer; //счетчики циклов

begin//обнуляем координаты курсорах : = ' ' ;у := " ;str := Socket.ReceiveText; //полученный от клиента текстfor i:=l to Length(str) dobegin

if str[i] <> '_' then x : = x + str[i]; //координаты по хif str[i] = '_' then Break; //разделитель между

//координатами указателяend;for j:=i+l to Length(str) do y:=y+str[j]; //координаты по у |//устанавливаем новые координаты указателяSetCursorPos(StrToInt(x), StrToInt(y) ) ;

end;

procedure TForml.FormPaint(Sender: TObject);

beginForml.Hide;

end;

end.

Полный код модуля клиентской программы представленв листинге 16.2.

Page 150: Delphi учимся на примерах

Полный исходный код модулей 149

Листинг 16.2. Модуль клиентской программы

| unit Unitl;

''. interface

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

typeTForml = class(TForm)

Buttonl: TButton;Button2: TButton;Client: TClientSocket;Timer1: TTimer;port: TEdit;ip: TEdit;Label1: TLabel;Label2: TLabel;procedure Button2Click(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure ButtonlClick(Sender: TObject);procedure TimerlTimer(Sender: TObject);procedure ClientConnect(Sender: TObject;

Socket: TCustomWinSocket);procedure ClientDisconnect(Sender: TObject;

Socket: TCustomWinSocket);private

{ Private declarations }public

{ Public declarations }end;

var

Forml: TForml;

implementation

($R *.dfm}

procedure TForml.Button2Click(Sender: TObject);

beginEimerl.Enabled := False; //выключаем таймерClient.Close; //закрываем соединениеClient.Active := False; //отключаемся от сервера

end;

Page 151: Delphi учимся на примерах

150 Удаленное управление указателем мыши

Листинг 16.2. Окончание

! procedure TForml.FormDestroy(Sender: TObject);begin

Client.Close;Client.Active := False;

end;

procedure TForml.ButtonlClick(Sender: TObject);

begin

Client.Port := StrToInt(port.Text); //считываем портClient.Address := ip.Text; //считываем ip-адрес сервераClient.Active := True; //соединяемсяtimerl.Enabled := True; //включаем таймер

end;

procedure TForml.TimerlTimer(Sender: TObject);var

cur: TPoint; //хранит координаты курсора мышиbegin

GetCursorPos(cur); //узнаем координаты указателя мыши//отправляем данные на сервер

Client.Socket.SendText(IntToStr(cur.X) + '_' +IntToStr(cur.Y));

end;

procedure TForml.ClientConnect(Sender: TObject;Socket: TCustomWinSocket);

begin//сообщение при соединении с серверомShowMessage('Connected!');

end;

procedure TForml.ClientDisconnect(Sender: TObject;

Socket: TCustomWinSocket);begin

//сообщение при отключении от сервераShowMessage('Disconnected! ' ) ;

end;

end.

Все файлы проекта и исполняемый файл клиентской программы находятся наприлагаемом к книге компакт-диске в папке C h a p t e r 1 6 \ C l i e n t , а файлыпроекта и исполняемый файл серверной программы — в папке Chap-t e r 1 6 \ S e r v e r .

Page 152: Delphi учимся на примерах

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

Глава 17

Бесплатная отправка SMS черезInternet

Постановка задачиРазработать программу для бесплатной отправки SMS через

Internet. Осуществлять отправку через сайты популярных украинскихоператоров ("UMC", "Джине", "Киевстар"...)

Разработка формыДля того чтобы отправить SMS, необходимо знать номер телефона,

на который мы будем отправлять сообщение, оператора этого номера и,естественно, — само отправляемое сообщение.

Создайте новый проект Delphi и присвойте форме заголовок SMS-sender (свойство Caption),, Разместите на форме компонент Label ка-тегории Standard и присвойте его свойству Caption значение Опера-тор: . Справа от него разместите компонент ComboBox (раскрывающий-ся список) категории Standard и измените его свойства согласнотабл. 17.1.

Примечание

Свойство ComboBox. I t e m s — это список строк, редактируемый в специальномокне, которое открывается по двойному щелчку мышью в соответствующем полеинспектора объектов.

Таблица 17.1. Свойства компонента ComboBox

Свойство

Name

T e x t

I t e m s

Значение

o p e r

<Выберите о п е р а т о р а >

Джине (066)

UMC (050)

К и е в с т а р (067)

Пояснение

Новое имя компонента

Текст в поле

Перечень операторов, на кото-

рых мы будем отправлять SMS

Page 153: Delphi учимся на примерах

152 Бесплатная отправка SMS через Internet

ПримечаниеВ данном примере используется перечень мобильных операторов, действующихна территории Украины. Если вы живете в другой стране, используйте собствен-ный список операторов.

Под первой меткой разместите еще один компонент Label, присво-ив его свойству Caption значение Номер:. Справа от него разместитекомпонент Edit категории Standard и назовите его t e l (свойство Name).

Ниже этих двух компонентов разместите компонент Label с тек-стом Сообщение: (свойство Caption). Под ним разместите компонентMemo категории Standard, присвоив ему имя sms. Для него можно поста-вить ограничение на ввод 160 символов, поскольку мобильные операто-ры обычно разрешают отправлять с Web-сайта сообщения длиной небольше 160 символов. Для того чтобы установить это ограничение, при-свойте свойству sms .MaxLength значение 160.

Для отображения количества символов, введенных в поле sms, раз-местите под memo-полем компонент Label и измените его свойства со-гласно табл. 17.2.

Таблица 17.2. Свойства компонента L a b e l для отображения длины сообщения

Свойство

Name

C a p t i o n

F o n t . C o l o r

F o n t . S i z e

Значение

k o l v o

0

c l R e d

18

Пояснение

Новое имя компонента

Надпись метки

Цвет надписи — красный

Размер шрифта

В правом нижнем углу формы разместите кнопку (компонент But-ton категории Standard), присвоив ее свойству Caption значение От-править.

Для отправки SMS нам понадобится компонент для передачи элек-тронной почты через SMTP. Такой компонент есть на вкладке FastNet иназывается он NMSMTP. Для того чтобы установить некоторые настрой-ки, у вас должен быть собственный адрес электронной почты. Бесплат-ных почтовых серверов в Internet предостаточно, так что с этим проблемвозникнуть не должно.

В рассматриваемом примере будет фигурировать адрес электроннойпочты автора ([email protected]). При желании, все перечислен-ные ниже настройки, конечно же, можно заменить собственными.

Page 154: Delphi учимся на примерах

Разработка программного кода 153

В свойстве NMSMTP1. Host следует указать smtp-сервер. Для yan-

dex, ru это свойство должно принять значение smtp.yandex.ru.

В свойстве User ID необходимо указать логин отправителя — указыва-

ем heel-adm. Теперь разверните свойство PostMessage и измените

значение вложенного свойства FromAddress на heel-adm@yandex . ru,

a FromName — на hee l-adm. Значение свойства P o r t измените на 25.

Полученная в результате форма должна соответствовать рис. 17.1.

- \а\ х|

Оператор: •

• • Номер: •

<Выберитеоперэтора> 3

11565394

Текст сообщения: •

О Отправить

Рис. 17.1. Форма программы для отправки SMS

Разработка программного кода

HL? Дprocedure TForml.ButtonlClick(Sender: TObject);varnum: string; //адрес получателя

beginNMSMTP1.PostMessage.Body.Clear; //очищаем текст письма//помещаем SMS в текст письмаNMSMTP1.PostMessage.Body.AddStrings(sms.Lines);//проверяем, какого оператора выбрал пользовательcase oper.Itemlndex of

0: num := '38066'+tel.Text+'@sms.jeans.com.ua'; //Джине1: num := '38050'+tel.Text+'@sms.umc.com.ua'; //UMC2: num := '38067'+tel.Text+'@sms.kyivstar.net'; //Киевстар

end;NMSMTP1.PostMessage.ToAddress.Add(num); //адрес получателяNMSMTP1.Connect; //соединяемся с серверомNMSMTP1.SendMail; //отправляем почту

Page 155: Delphi учимся на примерах

154 Бесплатная отправка SMS через Internet

NMSMTPl.Disconnect; //отсоединяемся от сервера//выводим сообщение об успешной отправкеShowMessage('Сообщение отправлено! '+ num);

I end;

Сначала мы проверяем: какого оператора выбрал пользователь. Ес-ли "Джине", то добавляем перед номером телефона "38066", если"UMC", то добавляем "38050", для "Киевстар" — "38067".

После того как мы узнали номер оператора, добавляем его к вве-денному номеру телефона и затем добавляем все это к адресу сервераоператора. Например, для отправки на номер "Джине" 1565394, делаемсвязку "38066"+" 1565394"+"@sms.jeans.com.ua".

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

Для того чтобы пользователь видел, сколько символов он ввел, имог контролировать длину SMS, реализуем подсчет символов при вводесообщение. Для этого следует обработать событие sms .OnChange:I procedure TForml.smsChange(Sender: TObject);

begin//количество введенных символовkolvo.Caption := IntToStr(Length(sms.Text));

end;

Количество введенных символов отображается в метке kolvo. Про-грамма отправки сообщений SMS в действии представлена на рис. 17.2.

SMS-senderОператор: \йжшс[06Б)

Номер: ]1565394

Текст сообщения:

Privet, eto testovaya SMS, nado by udalit'ее srazu...

Test complete! Programma tabotaet!

93 I Отправить |

Рис. 17.2. Программа отправки SMS через Internet в действии

Page 156: Delphi учимся на примерах

Полный исходный код модуля 155

Полный исходный код модуляПолный код модуля программы отправки S M S через Internet пред-

ставлен в листинге 17.1.

Листинг 17.1. Модуль программы отправки SMS через Internet

I unit Unitl;

! interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, StdCtrls, Psock, NMsmtp;

typeTForml « class(TForm)

oper: TComboBox;sms: TMemo;Labell: TLabel;Label2: TLabel;tel: TEdit;

Label3: TLabel;Buttonl: TButton;

NMSMTP1: TNMSMTP;kolvo: TLabel;

procedure ButtonlClick(Sender: TObject);procedure smsChange(Sender: TObject);

private

{ Private declarations }public

{ Public declarations }end;

var

Forml: TForml;

implementation

{$R *.dfm}

procedure TForml.ButtonlClick(Sender: TObject);var

num: string; //адрес получателяbegin

NMSMTP1.PostMessage.Body.Clear; //очищаем текст письма//помещаем SMS в текст письма

Page 157: Delphi учимся на примерах

156 Бесплатная отправка SMS через Internet

Листинг 17.1. Окончание

NMSMTP1.PostMessage.Body.AddStrings(sms.Lines);//проверяем, какого оператора выбрал пользовательcase oper.Itemlndex of0: num := '38066'+tel.Text+'@sms.jeans.com.ua'• //Джине1: num := '38050'+tel.Text+'@sms.umc.com.ua'; //UMC2: num := '38067'+tel.Text+'@sms.kyivstar.net'; //Киевстар

end;NMSMTP1.PostMessage.ToAddress.Add(num); //адрес получателяNMSMTP1.Connect; //соединяемся с серверомNMSMTP1.SendMail; //отправляем почтуNMSMTP1.Disconnect; //отсоединяемся от сервера//выводим сообщение об успешной отправкеShowMessage{'Сообщение отправлено! '+ num) ;

end;

procedure TForml.smsChange(Sender: TObject);begin

//количество введенных символов

kolvo.Caption := IntToStr(Length(sms.Text));end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 17.

Page 158: Delphi учимся на примерах

Глава 18

FTP-клиент

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

Постановка задачиРазработать FTP-клиент. Программа должна соединяться с FTP-cep-

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

Разработка формыСоздайте новый проект Delphi. Приготовьтесь к тому, что форма

получится довольно большой (ширина — около 800 пикселей) и будетсодержать большое количество разных кнопок и полей ввода. Присвой-те ей заголовок FTP-client (свойство Caption) и разместите компо-ненты согласно табл. 18.1.

Таблица 18.1. Свойства формы FTP-клиента

Компонент

Labell(категорияStandard)

Label2

Label3

E d i t l(категорияStandard)

Свойство

Capt ion

L e f t

Top

Capt ion

L e f t

Top

Capt ion

L e f t

Top

Name

Text

L e f t

Top

Значение

FTP-сервер

56

16

Имя пользователя

16

48

Пароль

72

80

f t p s e r v e r

f t p . n a r o d . r u

120

8

Пояснение

Надпись метки

Отступ слева

Отступ сверху

Надпись метки

Отступ слева

Отступ сверху

Надпись метки

Отступ слева

Отступ сверху

Новое имя компонента

Адрес FTP-сервера

Отступ слева

Отступ сверху

Page 159: Delphi учимся на примерах

158 FTP-клиент

Таблица 18.1. Продолжение

Компонент

E d i t 2

E d i t 3

E d i t 4

E d i t 5

E d i t 6

E d i t 7

E d i t 8

E d i t 9

E d i t l O

B u t t o n l

(категория

Standard)

Свойство

Name

Text

L e f t

Top

Name

L e f t

Top

Name

Text

L e f t

Top

Name

L e f t

Top

Name

L e f t

Top

Name

L e f t

Top

Name

L e f t

Top

Name

L e f t

Top

Name

L e f t

Top

Capt ion

L e f t

Top

Значение

name

t e s t 6 0 0 1

120

40

pass

120

72

p o r t

21

120

104

d e l

512

8

cd

512

40

cmd

512

72

md

512

104

r d

512

136

download

512

168

Подключиться

8

144

Пояснение

Новое имя компонента

Имя пользователя

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Новое имя компонента

Имя пользователя

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Новое имя компонента

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Page 160: Delphi учимся на примерах

Разработка формы 159

Таблица 18.1. Продолжение

Компонент

Button2

Button3

Button4

Button5

Button6

Button7

Button8

Button9

Memo

(категория

Standard)

Свойство

Caption

Left

T o p

Caption

Left

T o p

Caption

Left

T o p

Caption

Left

T o p

Caption

Left

T o p

Caption

Left

T o p

Caption

Left

T o p

Caption

Left

T o p

Name

Lines

Left

T o p

Height

Width

Значение

Отключиться

123

144

Загрузить файл насервер

512

200

Удалить

672

8

Изменить каталог

672

40

Выполнить команду

672

72

Создать каталог

672

104

Удалить каталог

672

136

Скачать файл

672

168

statusl

Статус:

264

8

217

2 3 3

Пояснение

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Надпись на кнопке

Отступ слева

Отступ сверху

Новое имя компонен-

та, предназначенного

для отображения со-

стояния соединения

Текст в поле

Отступ слева

Отступ сверху

Высота

Ширина

Page 161: Delphi учимся на примерах

160 FTP-клиент

Таблица 18.1. Окончание

Компонент

O p e n D i a l o g(категорияDialogs)

S a v e D i a l o g

(категория

Dialogs)

NMFTP

(категория

FastNet)

Свойство

Name

Name

Name

Значение

Openl

S a v e l

f t p

Пояснение

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

Новое имя компонента, который

будет использоваться для сохра-

нения файлов

Новое имя главного компонента

программы

Полученная

I Jfc FTPcIleiJt:.:.::: FTP-cepeepi"Pnarodr

:: Имя пользователя И 6 0 0 1

Пароль- !

: Порт : I2 1

форма

Подключиться Отключиться |

:' ЪШЩг

должна

Статус:

соответствовать рис.

ИИИРГJ JFiteName:.К.

• JDirName- JDuNameJFileName

v I '

18.1.

— — '

Здгрузить Файл

- i n l x j

Удалить

Изменить каталог |

Выполнить команду \

Создать каталог

; Удалить каталог

Скачать Файл

на сервер

Рис. 18.1. Форма FTP-клиента

Разработка программного кодаОбработаем нажатия кнопок соединения и отключения от сервера.

для кнопки Подключиться:procedure TForml.ButtonlClick{Sender: TObject);begin

ftp.Host := ftpserver.Text; //ftp-серверftp.UserID := name.Text; //логинftp.Password := pass.Text; // парольftp.Port := StrToInt(port.Text); //порт для подключения//соединяемся с серверомif not ftp.Connected then ftp.Connect;

L e n d ;

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

Page 162: Delphi учимся на примерах

Разработка программного кода 161

^ j ^ j ^ j j Отключиться̂| procedure TForml.Button2Click(Sender: TObject);begin

if ftp.Connected then //если соединен

ftp.Disconnect; //отключиться от сервера

end;

Если при нажатии кнопки Отключиться установлено соединение с

сервером, то мы разрываем его.

Теперь обработаем нажатие кнопок, которые служат для работы с

(procedure TForml.Button4Click(Sender: TObject);begin

ftp.Delete(del.Text); //удалить файл

i end; _ _ _ _ _ _ _ _ _ _ _

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

нажатие кнопки Изменить каталог:procedure TForml.ButtonSClick(Sender: TObject);begin

ftp.ChangeDir(cd.Text); //изменяем каталог

end;

Устанавливаем текущим тот каталог, который указан в поле cd.

procedure TForml.Button6Click(Sender: TObject);begin

ftp.DoCommand(cmd.Text); //выполнение командыend;

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

Обработаемprocedure TForml.Button7Click(Sender: TObject);begin

ftp.MakeDirectory(md.Text); //создать каталог

end;

Обработаем нажатие кнопки Удалить каталог:I procedure TForml.Button8Click(Sender: TObject);

11 — 5-1212

Page 163: Delphi учимся на примерах

162 FTP-клиент

begin

ftp.RemoveDir(rd.Text); //удалить каталог

end;

Обработаем нажатие кнопки Скачать файл;procedure TForml.Button9Click(Sender: TObject);begin

//открытие диалогового окна сохранения файлаif Savel.Executethen //скачиваем указанный файл

ftp.Download(download.Text,savel.FileName)else ShowMessage('File not saved!

1); {если пользователь

отказался сохранять файл}end;

Сначала мы предлагаем пользователю указать имя и путь размеще-ния полученного файла. Затем мы загружаем файл и размещаем его поуказанному пути.

Наконец, обработаем нажатие кнопки Загрузить файл на сервер:procedure TForml.Button3Click(Sender: TObject);var

i: integer;FName, temp: string; //для получения имени файла

beginif not Openl.Execute then ShowMessage('Файл не выбран!')else begin

//очищаем переменные, которые содержат имя файлаtemp := ' ' ;

FName := '';//получаем имя файлаfor i:=Length(Openl.FileName) downto 1 dobegin

if Openl.FileName[i] = 'V then break;temp :• temp + Openl.FileName[i];

end;for i:=Length(temp) downto 1 do

fname := fname + temp[i];

ftp.Upload(Openl.FileName, FName); //загружаем файлend;

end;

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

В общем, наш ftp-клиент уже полностью работоспособен и выпол-няет все необходимые функции. Единственное, что осталось сделать, —

Page 164: Delphi учимся на примерах

Разработка программного кода 163

реализовать извещение пользователя о протекании всех операций и обовсех ошибках. Для этого следует создать несколько обработчиков собы-тий компонента f tp.

Событие в случае возникновения ошибки при проверке имени и па-L On Au t h е n t i с a t i о n F a i 1 e d:

procedure TForml.ftpAuthenticationFailed(var Handled:Boolean);

beginstatusl.Lines.Add('Неверное имя или пароль');

|j=md;

Событие при подключении — OnConnect:procedurebegin

statusl

TForml.ftpConnect(Sender

Lines.Add('Подключено');//локальный ip-адресstatusl Lines.Add('IP клиента: '//удаленный ip-адресstatusl

end;Lines.Add('IP сервера: '

: TObject);

+ ftp.LocallP);

+ ftp.RemotelP);

Событие в случае возникновения ошибки при подключении — On-Connect ionFai led:procedurebegin

statusl

end;

TForml

.Lines.

.ftpConnectionFailed(Sender:

Add('He удалось подключиться

TObject);

к серверу');

Событие при отключении от сервера — OnDis connect:procedure TForml.ftpDisconnect(Sender: TObject);

j beginstatusl.Lines.Add('Отключено');

end;

Событие в случае возникновения tprocedure TForml.ftpError(Sender:Errmsg: String);begin

statusl.Lines.Add('Ошибка: ' +end;

TComponent ;

errmsg);

гоки — OnError:Errno: Word;

Событие в случае возникновения ошибки при подключении к сер-вер_у_—Onlrrva I i dHo s t:procedurebegin

statusl

end;

TForml

.Lines.

.ftpInvalidHost

Add('Ошибка при

(var Handled:

подключении

Boolean);

к серверу');

И*

Page 165: Delphi учимся на примерах

164 FTP-клиент

Событие при изменении состоянияj procedure TForml.ftpStatus(Sender: TComponent;

Status: String);begin

statusl.Lines.Add(Status);

end;

I procedure TForml.ftpSuccess(Trans_Type: TCmdType);begin

statusl.Lines.Add('Успешно') ;; end;

procedure TForml.ftpTransactionStart(Sender: TObject);j begin

statusl.Lines.Add('Начало передачи данных');

procedure TForml.ftpTransactionStop(Sender: TObject);begin

statusl.Lines.Add('Конец передачи данных1);

end;

Теперь программа полностью готова к использованию. Если у васнет собственного Web-сайта, то для тестирования FTP-клиента можетезарегистрировать сайт на бесплатном хостинге.

Полный исходный код модуляПолный код программного модуля FTP-клиента представлен

в листинге 18.1.

Листинг 18.1. Программный модуль FTP-клиента

unit Unitl;

interface

usesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms, Dialogs, NMFtp, StdCtrls, Psock;

typeTForml = class(TForm)

ftp: TNMFTP;ftpserver: TEdit;

Page 166: Delphi учимся на примерах

Полный исходный код модуля 165

Листинг 18.1. Продолжение

Labell: TLabel;Label2: TLabel;name: TEdit;Label3: TLabel;pass: TEdit;Label4: TLabel;port: TEdit;

Buttonl: TButton;Button2: TButton;statusl: TMemo;Button3: TButton;Openl: TOpenDialog;Button4: TButton;del: TEdit;Button5: TButton;cd: TEdit;cmd: TEdit;

Button6: TButton;md: TEdit;

Button7: TButton;rd: TEdit;

Button8: TButton;download: TEdit;

Button9: TButton;Savel: TSaveDialog;procedure ButtonlClick(Sender: TObject);procedure ftpStatus(Sender: TComponent; Status: String);procedure ftpError(Sender: TComponent; Errno: Word;

Errmsg: String);procedure ftpDisconnect(Sender: TObject);procedure ftpConnect(Sender: TObject);procedure ftpConnectionFailed(Sender: TObject);procedure ftpInvalidHost(var Handled: Boolean);procedure ftpSuccess(Trans_Type: TCmdType);procedure ftpTransactionStart(Sender: TObject);procedure ftpTransactionStop(Sender: TObject);procedure ftpAuthenticationFailed(var Handled: Boolean);procedure Button2Click(Sender: TObject)procedure Button3Click(Sender: TObject)procedure FormDestroy(Sender: TObject);procedure Button5Click(Sender: TObject)procedure Button4Click(Sender: TObject)procedure Button6Click(Sender: TObject)procedure Button7Click(Sender: TObject)procedure Button8Click(Sender: TObject)

Page 167: Delphi учимся на примерах

166 FTP-клиент

Листинг 18.1. Продолжение

procedure Button9Click(Sender: TObject);private

{ Private declarations }public

{ Public declarations }end;

var

Forml: TForml;

implementation

{$R *.dfm}

procedure TForml.ButtonlClick(Sender: TObject);begin

ftp.Host := ftpserver.Text; //ftp-серверftp.UserlD := name.Text; //логинftp.Password := pass.Text; // пароль

ftp.Port := StrToInt (port.Text); //порт для подключения//соединяемся с серверомif not ftp.Connected then ftp.Connect;

end;

procedure TForml.ftpStatus(Sender: TComponent;Status: String);

begin

statusl.Lines.Add(Status) ;end;

procedure TForml.ftpError(Sender: TComponent; Errno: Word;Errmsg: String);begin

statusl.Lines.Add('Ошибка: ' + Errmsg);end;

procedure TForml.ftpDisconnect(Sender: TObject);begin

statusl.Lines.Add('Отключено ' ) ;end;

procedure TForml.ftpConnect(Sender: TObject);begin

statusl.Lines.Add('Подключено' ) ;

Page 168: Delphi учимся на примерах

Полный исходный код модуля 167

Листинг 18.1. Продолжение

statusl.Lines.Add('IP клиента: ' + ftp.LocallP);statusl.Lines.Add('IP сервера: ' + ftp.RemotelP);

end;

procedure TForml.ftpConnectionFailed(Sender: TObject);

begin

statusl.Lines.Add('He удалось подключиться к серверу');end;

procedure TForml.ftpInvalidHost(var Handled: Boolean);

beginstatusl.Lines.Add('Ошибка при подключении к серверу');

end;

procedure TForml.ftpSuccess(TransJType: TCmdType);

begin

statusl.Lines.Add('Успешно');

end;

procedure -TForml.ftpTransactionStart(Sender: TObject);

begin

statusl.Lines.Add('Начало передачи данных');

end;

procedure TForml.ftpTransactionStop(Sender: TObject);

begin

statusl.Lines.Add('Конец передачи данных');

end;

procedure TForml.ftpAuthenticationFailed(var Handled:

Boolean);

begin

statusl.Lines.Add('Неверное имя или пароль');

end;

procedure TForml.Button2Click(Sender: TObject);

beginif ftp.Connected then //если соединен

ftp.Disconnect; //отключиться от сервера

end;

procedure TForml.Button3Click(Sender: TObject);

vari: integer;FName, temp: string; //для получения имени файла

Page 169: Delphi учимся на примерах

168 FTP-клиент

Листинг 18.1. Продолжение

I begin

if not Openl.Execute then ShowMessage('Файл не выбран!')

else begin

//очищаем переменные, которые содержат имя файлаtemp : = ' ' ;FName : ̂ ' ';//получаем имя файлаfor i:=Length(Openl.FileName) downto 1 do begin

if Openl.FileName[i] = '\' then break;temp := temp + Openl.FileName[i];

end;for i:"Length(temp) downto 1 do fname := fname + tempfi];ftp.Upload(Openl.FileName, FName); //загружаем файл

end;end;

procedure TForml.FormDestroy(Sender: TObject);begin

if ftp.Connected then ftp.Disconnect;end;

procedure TForml.Button5Click(Sender: TObject);begin

ftp.ChangeDir(cd.Text) ;end;

procedure TForml.Button4Click(Sender: TObject);begin

ftp.Delete(del.Text); //удалить файлend;

procedure TForml.Button6Click(Sender: TObject);begin

ftp.DoCommand(crad.Text); //выполнить командуend;

procedure TForml.ButtonVClick(Sender: TObject);begin

ftp.MakeDirectory(md.Text); //создать каталогend;

procedure TForml.Button8Click(Sender: TObject);begin

ftp.RemoveDir(rd.Text); //удалить каталогend;

Page 170: Delphi учимся на примерах

Полный исходный код модуля 169

Листинг 18.1. Окончание

procedure TForml.Button9Click(Sender: TObject);begin

//открытие диалогового окна сохранения файлаif Save!.Executethen //скачиваем указанный файл

ftp.Download(download.Text,savel.FileName)else ShowMessage('File not saved!'); (если пользователь

отказался сохранять файл}end;

end.

Все файлы проекта и исполняемый файл рассмотренной программы находятсяна прилагаемом к книге компакт-диске в папке C h a p t e r 18.

Page 171: Delphi учимся на примерах

170 Написание CGI-приложений

Глава 19

Написание CGI-приложений

Постановка задачиРазработать CGI-сценарий на Delphi. В качестве примера, при акти-

вации через форму сценарий будет выводить определенную фразу.

Разработка проектаК удивлению некоторых программистов, в Delphi можно разраба-

тывать CGI-сценарии. Для примера, разработаем сценарий, при обраще-нии к которому будет создаваться HTML-страница с текстом "Это мойпервый CGI-сценарий".

Поскольку это будет не обычная выполняемая программа, то стан-дартный проект, который по умолчанию предлагает нам Delphi, не под-ходит. Выполните команду меню File -> New -» Other, в результате чегооткроется диалоговое окно New Items (рис. 19.1).

| ' New Items

Projects I Data Modules j Business | WebSnap j WebServicesNew I ActiveX I Multitier j Pfojecr.2 I Forms j Dialogs

• "Application Batch File CIX CLXData CLXFormApplication ModuleCLX Frame Component Control Panel Control PanelApplication Module

•Data Module DLL Wizard Form Frame Package

Г Copy Г Inherit Г ij-.s .••'••',. :

OK j Cancel I Help

Рис. 19.1. Диалоговое окно New Items

Page 172: Delphi учимся на примерах

Разработка проекта 171

Выберите тип программы Console Application и нажмите кнопку ОК.В появившемся окне сотрите весь текст и введите следу_ющий код:

program c g i _ t e s t ; //название сценария

{$APPTYPE CONSOLE}

{$Е cgi} //расширение приложения будет .cgibegin

//способ отображения - text/htmlWriteLn('Content-Type: text/html');WriteLn;

WriteLn;WriteLn('<HTML>'); //начало страницыWriteLn('<HEAD>•);//заголовокWriteLn('<TITLE>nepBbrii cgi-сценарий на Delphi</TITLE>');

//колировка и тип содержимогоWriteLn('<МЕТА http-equiv="Content-Type" ' +

1content="text/html; charset=windows-1251">');

WriteLn('</HEAD>•);

WriteLn('<BODY>');

WriteLn(' < H 1 X C E N T E R > _ T O МОЙ первый CG_-C4_Haprat</CENTER>'+'</Н1>'); //выводим текст большими жирными буквами

WriteLn('</BODY>');WriteLn('</HTML>');

end.

Откомпилируйте приложение и присвойте ему имя c g i _ t e s t . cgi.Этот CGI-сценарий при обращении к нему создает страницу с заголов-ком "Первый cgi-сценарий на Delphi" и большим текстом на странице:"Это мой первый CGI-сценарий".

Теперь необходимо создать Web-страницу, которая будет обра-щаться к этому сценарию. Создайте файл с расширением . html сле-дующего содержимого:<HTML><HEAD><Т1ТЬЕ>Первый cgi-сценарий на Delphi</TITLE></HEAD><BODY><FORM method="POST" action="cgi/cgi_test.cgi" method="POST"><input type="submit" уа1ие="Вьшолнить">

</FORM>

<р><Ь>Также вы можете выполнять сценарии, просто делая на нихссылку: </b><a href="cgi/cgi_test.сд1">ссылка на cgi-сценарий</а></BODY></HTML>

Page 173: Delphi учимся на примерах

172 Написание CGI-приложений

Это форма с кнопкой, которая активизирует CGI-сценарий(рис. 19.2).

© П е р в ы й cql сценарий нл Delphi - МогШа I ' k c f m

файл Правка §ид Переход 2акл*Лки инструменты Сврадкг

. • • № "с к http://locatiostycgLtest.htmlCustomize links i Free Hotma» ... Windows , Window» MedU

Выполнить

JBJ xj

0 Перейти |iCi,

Рис. 19.2. Web-страница для вызова CGI-сценария

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

В ответ должна быть отображена новая страница с текстом "Этомой первый CGI-сценарий" (рис. 19.3).

•КЗПервый cgi-сценарий на Delphi - Mozilla FirefoK

Правка Вид Переход £акладки инструменты Справка

© Перейти jIGJ,.

; Customtee Links \_) Free Hotmail . Windows [jj Windows Media

Это мой первый CGI-сценарий

Рис. 19.3. Страница, выданная CGI-сценарием c g i _ t e s t . c g i

Все файлы рассмотренного проекта находятся на прилагаемом к книге компакт-диске в папке C h a p t e r 19.

Page 174: Delphi учимся на примерах

173

Приложение А

Коды клавиш и их значения

Коды клавиш в десятичном и шестнадцатеричном представлении, а

также соответствующие константы и функции Ord перечислены в табл. АЛ.

Таблица А.1. Коды клавиш и соответствующие константы

Клавиша

а, А

ь, вс, С

d, D

е, Е

f, F9.G

h, H

I, I

i.Jk, К

I, Lm, M

n, N

o,O

P, Pq,Q

r, R

s, S

t, T

u, Uv, V

w, W

x, X

Код в десятичном

представлении

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

8687

88

Код в шестнадцате-

ричном представлении

$41

$42

$43

$44

$45

$46

$47

$48

$49

$4А

$4В

$4С

$4D

$4Е$4F

$50

$51

$52

$53

$54

$55

$56

$57

$58

КонстантаФункция

ord

ord ( 'Л ' )

o r d ( ' B ' )

o r d ( ' С )

ord (' D' )

o r d ( ' E ' )

o r d C F ' )

o r d ( ' G ' )

o r d ( ' H ' )

o r d C I ' )

ordС J ' )

ordС К')

o r d C L ' )

ord( 'M')

o r d ( ' N ' )

ord ('O' )

ord (' P' )

o r d C Q ' )

o r d ( ' R ' )

o r d ( ' S ' )

o r d l ' T ' )

o r d C U ' )

ord ( ' V )

ordl 'W' )

o r d ( ' X ' )

Page 175: Delphi учимся на примерах

174 Коды клавиш и их значения

Таблица А.1. Продолжение

Клавиша

У.У

z, Z

0

1

2

3

4

5

6

7

8

9*

+

-

/

F1

F2

F3

F4

F5

F6

F7

F8

F9

F10

пробел

Backspace

Tab

Enter

Shift

Код в десятич-

ном представ-

лении

89

90

96

97

98

99

100

101

102

103

104

105

106

107

109

110

111

112

113

114

115

116

117

118

119

120

121

32

8

9

13

16

Код в шестнадца-

теричном пред-

ставлении

$59

$5А

$60

$61

$62

$63

$64

$65

$66

$67

$68

$69

$6А

$6В

$6D

$6Е

$6F

$70

$71

$72

$73

$74

$75

$76

$77

$78

$79

$20

$8

$9

$0D

$10

Константа

VK NUMPAD0

VK NOMPAD1

VK NUMPAD2

VK NUMPAD3

VK NUMPAD4

VK NUMPAD5

VK NUMPAD6

VK NUMPAD>

VK NUMPAD8

VK NUMPAD9

VK MULTIPLY

VK ADD

VK SUBTRACT

VK DECIMAL

VK DIVIDE

VK F l

VK F2

VK F3

VK F4

VK F5

VK F6

VK F7

VK F8

VK F9

VK F 1 0

VK SPACE

VK BACK

VK TAB

VK RETURN

VK SHIFT

Функция

ord

o r d e r )

ord(' Z' )

Page 176: Delphi учимся на примерах

175

Таблица А.1. Окончание

Клавиша

Ctrl

Alt

CapsLock

Esc

Insert

PageUp

PageDown

End

Home

<—

t—>1

Delete

PrintScreen

ScrollLock

Pause

Numlock

Код в деся-

тичном пред-

ставлении

17

18

20

27

45

33

34

35

36

37

38

39

40

46

44

145

19

144

Код в шестнадцате-

ричном представле-

нии

$11

$12

$14

$1В

$2D

$21

$22

$23

$24

$25

$26

$27

$28

$2Е

$2С

$91

$13

$90

Константа

VK CONTROL

VK MENU

VK CAPITALE

VK ESCAPE

VK INSERT

VK PRIOR

VK NEXT

VK END

VK HOME

VK LEFT

VK UP

VK RIGHT

VK DOWN

VK DELETE

VK SNAPSHOT

VK SCROLL

VK PAUSE

VK NUMLOCK

Функция

ord

Page 177: Delphi учимся на примерах

176 Kylix — Delphi для Linux

Приложение Б

Kylix — Delphi для Linux

В 2001 году компания Borland International, разработавшая Delphi,выпустила продукт под названием Kylix, Kylix— это среда быстройразработки приложений для Linux. Интерфейсом она почти ничем неотличается от привычного Delphi, а язык программирования, которыйиспользует Kylix просто не может не радовать — это Object Pascal. Ко-роче говоря, Kylix — это тот же Delphi, только для ОС Linux. Корпора-ция Borland предлагает два основных варианта Kylix: Kylix Desktop De-veloper и Kylix Server Developer. Наиболее полной версией по возмож-ностям и функциональности является Kylix Server Developer.

Существует возможность переносить программы из Delphi в Kylix(само собой, если у программ нет привязки к ОС — например, исполь-зования функций WinApi). Стоит сказать несколько слов о совместимо-сти и переносимости исходных кодов программ с Delphi в Kylix. Как из-вестно, в Delphi используется библиотека классов VCL. Для Kylix этабиблиотека называется CLX (библиотека компонентов для кросс-платформенной разработки). Впрочем, они довольно совместимы, и вVCL присутствует почти полная поддержка библиотеки классов CLX.

Еще одно небольшое отличие заключается в расширении файлов,содержащих описание форм. В Delphi эти файлы имеют расширение*. dfm, а в Kylix — * . xfm. Это не создает особых неудобств, простов программах следует изменить директиву {$R . dfm} на {$R . xfm}.

В Kylix, в отличие от Delphi, отсутствует возможность работы с ба-зами данных BDE и ADO. Отсутствует поддержка ActiveX, COM иCORBA. Невзирая на все перечисленные недостатки и аспекты несо-вместимости с Delphi, Kylix является довольно удобной средой про-граммирования. Тот кто программирует на Delphi, сможет перейти наKylix без особых затруднений.

Page 178: Delphi учимся на примерах

Общая настройка ПК 177

Приложение В

Справочник по реестру Windows

Ниже описаны интересные ключи системного реестра Windows. Ихможно изменять программно или вручную, используя стандартную про-грамму для работы с реестром r e g e d i t . exe. Используя эти ключи рее-стра, можно расширить шаблон программы для настройки Windows,рассмотренный в главе 12.

Общая настройка ПК

Изменение разрешения экрана

Для изменения разрешения экрана (например, на 800x600) следуетвнести следующие изменения в реестр:

Ключ:[HKEY_LOCAL_MACHINE\Config\0001\Display\Settings].

Значение ключа:"Resolution" = "800, 600"

Установка задержки перед появлением контекстногоменю

Для того чтобы установить задержку появления контекстного менюв 10 миллисекунд следует создать такой ключ:

[HKEY_CURRENT__USER\Control Panel\desktop]

"MenuShowDelay"="10"

Сокрытие изображение стрелки на ярлыках

Для того чтобы убрать изображение стрелки на ярлыках, создайтеследующие два ключа:

[HKEY_CLASSES_ROOT\piffile]

"IsShortcut"=""

[HKEY_CLASSES__ROOT\lnkfile]

"IsShortcut"=""

12 — 5-1212

Page 179: Delphi учимся на примерах

178 Справочник по реестру Windows

Сокрытие приставки "Ярлыкдля..."

Для того чтобы у создаваемых ярлыков не было приставки "Ярлыкдля...", измените следующий ключ:

[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Explorer]

"LinkM=hex:00,00,00,00

Запрет на редактирование реестра

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Policies\System]

Значение:"DisableRegistryTools"=dword:00000001

Отключение динамика ПК

Ключ:[HKEY_CURRENT_USER\Control Panel\Sound]

Значение:"Beep"="No"

Включение динамика ПК

Ключ:[HKEY_CURRENT_USER\Control Panel\Sound]

Значение:"Beep"="Yes"

Отключение возможности автозапуска с CD-ROM

Ключ:[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services

\CDRom]

Значение:"Autorun"=dword:00000000

Page 180: Delphi учимся на примерах

Общая настройка ПК 179

Отключение всплывающих подсказок в Проводнике и наРабочем столе

Ключ:[HKEY_CURRENT__USER\Software\Microsoft\Windows\Current

Version\Explorer\Advanced]Значение:"ShowInfoTip"=dword:00000000

Автоматическое наведение указателя мыши на активнуюкнопку

Ключ:[HKEY_CURRENT_USER\ControlPanel\Mause]Значение:"SnapToDefaultButton"="l"

Отключение возможности открывать диспетчер задач

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Policies\System]

Значение:"DisableTaskMgr"=dword:00000001

Отключение возможности восстановления системы

Ключ:[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windo

ws NT\SystemRestore]

Значение:"DisableConfig"=dword:00000001

Очистка swap при выключении компьютера

Ключ:[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\

Session Manager\Memory Management]

Значение:

"ClearPageFileAtShutdown"=dword: 00000001

12*

Page 181: Delphi учимся на примерах

180 Справочник по реестру Windows

Изменение размещения папок и каталогов

Изменение размещения папки Избранное

Для того чтобы изменить размещение папки Избранное, следуетнаписать новый путь к этой папке в следующий ключ:

[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Explorer\User Shell Folders]

"Favorites"="C:\\Избранное"

Изменение каталога по умолчанию для программ

Можно изменить предлагаемый системой по умолчанию каталогпри установке программ:

[HKEY_LOCALJVIACHINE\SOFTWARE\Microsoft\Windows\Curren

tVersion]

"ProgramFilesDir"="C:WProgram Fi les"

"ProgramFilesPath"="C:WProgram Fi les"

Сокрытие пунктов системного меню Пуск

Сокрытие пункта Пуск —> Найти

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Explorer]

Значение:

"NoFind"=dword:0

Сокрытие пункта Пуск -* Программы —> Стандартные

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Explorer]

Значение:"NoComnonGroups"=dword:00000001

Сокрытие пункта Пуск -* Избранное

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

VersionXExplorer]

Page 182: Delphi учимся на примерах

Сокрытие пунктов системного меню Пуск 181

Значение:"NoFavoritesMenu"=dword:00000001

Сокрытие пункта Пуск —> Документы

Ключ:[HKEY_CURRENT JJSER\Software\Microsoft Windows\Current

Version\Explorer]

Значение:"NoRecentDocsMenu"=dword:00000001

Сокрытие пункта Пуск —> Панель управления

Ключ:[HKEY__CURRENT_USER\ So ftware\Microso ft Windows \Cur rent

Version\Policies\Explorer]

Значение:"NoContro1Panel"=dword:00000001

Сокрытие пункта Пуск —• Выполнить

Ключ:[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

VersionXPolicies\Explorer]

Значение:"NoRun"=dword:00000001

Сокрытие пункта Пуск —> Настройка —> Принтеры

Для того чтобы скрыть пункты меню Пуск —> Панель управления.Пуск -» Настройка -» Принтеры (и соответствующие пиктограммы в пап-ке Мой компьютер), внесите следующие изменения в реестр:

[HKEY_CURRENT_USER\Software\Microsoft Windows\Current

Version\Explorer]

"NoSetFolders"=dword:00000001

Сокрытие пункта Пуск —• Настройка —> Панель задач

Ключ:[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

Version\Explorer]

Значение:

"NoSetTaskbar"=dword:00000001

Page 183: Delphi учимся на примерах

182 Справочник по реестру Windows

Сокрытие пункта Пуск —* Завершение сеанса

Ключ:[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

Version\Explorer]Значение:" N o L o g O f f " = h e x : 0 1 , 0 0 , 0 0 , 00

Сокрытие пункта Пуск -* Выключить компьютер

Ключ:

[HKEY_CURRENT_USER\Software\MicrosoftWindows\CurrentVersion\Explorer]

Значение:"NoClose"=dword:00000001

Сокрытие всех дополнительных папок в меню Пуск

Ключ:

[HKEY_CURRENT_USER\Software\MicrosoftWindows\CurrentVersion\Policies\Explorer]

Значение:"NoStartMenuSubFolders"=dword:00000001

Сокрытие папки Мок документы в меню Пуск

Ключ:

[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

Version\Explorer\Documents]

Значение:

"DisableStartInMyDocs"=dword:00000001

Сокрытие различных элементов интерфейса

Сокрытие дисков в папке Мой компьютер

В папке Мой компьютер можно скрывать диски. Ниже представле-ны имена дисков и соответствующий ключ для их сокрытия. Для тогочтобы скрыть сразу несколько дисков, суммируйте значения ключей:

[HKEY_CURRENTJJSER\Software\MicrosoftWindows\CurrentVersion\Explorer]

A: "NoDrives"=dword:00000001

Page 184: Delphi учимся на примерах

Сокрытие различных элементов интерфейса 183

В: "NoDrives"=dword:00000002

С: "NoDrives"=dword:00000004

D: "NoDrives"=dword:00000008

Е: "NoDrives"=dword:00000010

F: "NoDrives"=dword:00000020

G: "NoDrives"=dword:00000040

H: "NoDrives"=dword:00000080

I : "NoDrives"=dword:00000100

J: "NoDrives"=dword:00000200

K: "NoDrives"=dword:00000400

L: "NoDrives"=dword:00000800

M: "NoDrives"=dword:00001000

N: "NoDrives"=dword:00002000

0: "NoDrives"=dword:00004000

P: "NoDrives"=dword:00008000

Q: "NoDrives"=dword:00010000

R: "NoDrives"=dword:00020000

S: "NoDrives"=dword:00040000

T: "NoDrives"=dword:00080000

U: "NoDrives"=dword:00100000

V: "NoDrives"=dword:00200000

W: "NoDrives"=dword:00400000

X: "NoDrives"=dword:00800000

Y: "NoDrives"=dword:01000000

Z: "NoDrives"=dword:02000000

Для того чтобы скрыть все диски:"NoDrives"=dword:03FFFFFF

Сокрытие пиктограммы Принтеры в панели управления

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Explorer]

Значение:"NoPrinters"=dword:00000001

Page 185: Delphi учимся на примерах

184 Справочник по реестру Windows

Сокрытие вкладок Общие и Сведения в окне свойствпринтера

Ключ:[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

VersionXExplorer]

Значение:"NoPrinterTabs"=dword:00000001

Настройка Рабочего стола

Сокрытие всех элементов Рабочего стола

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

VersionXExplorer]

Значение:"NoDesktop"=dword:00000001

Сокрытие пиктограммы Internet на Рабочем столе

Ключ:[HKEY_CURRENT__USER\Software\Microsoft\Windows\Current

VersionXExplorer]

Значение:"Nolnternetlcon"=dword:00000001

Сокрытие пиктограммы Сетевое окружение на Рабочемстоле

Ключ:[HKEY_CURRENTJJSER\Software\Microsof t:\Windows\Current

VersionXExplorer]

Значение:"NoNetHood"=dword:00000001

Отключение возможности вызывать окно свойств экрана

Ключ:

[HKEY_CURRENTJ3SER\Software\Microsoft\Windows\Current

VersionXPoliciesXSystem]

Page 186: Delphi учимся на примерах

Сокрытие вкладок окна свойств экрана 185

Значение:"NoDispCPL"=dword:00000001

Отключение контекстного меню панели задач

Ключ:[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

VersionXPolicies\Explorer]Значение:"NoTrayContextMenu"=hex:01,00,00,00

Отключение контекстного меню Рабочего стола

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

VersionXPolicies\Explorer]Значение:" N o V i e w C o n t e x t M e n u " = h e x : 0 1 , 0 0 , 0 0 , 00

Сокрытие папки Мои документа на Рабочем столе

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Explorer\Documents]

Значение:"HideMyDocsFolder"=dword:00000001

Сокрытие вкладок окна свойств экрана

Сокрытие вкладки Оформление

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Policies\System]Значение:"NoDispAppearancePage"=dword:00000001

Сокрытие вкладки Фон

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

VersionXPolicies\System]

Page 187: Delphi учимся на примерах

186 Справочник по реестру Windows

Значение:"NoDispBackgroundPage"=dword:00000001

Сокрытие вкладки Заставка

Ключ:[HKEY_CURRENT_USER\Software\MicrosoftWindows\Current

VersionXPolicies\Systern]

Значение:"NoDispScrSavPage"=dword:00000001

Сокрытие вкладки Параметры

Ключ:[HKEY_CURRENT_USER\Software\Microsoft\Windows\Current

Version\Policies\System]

Значение:"NoDispSettingsPage"=dword:00000001

Настройка браузера Internet Explorer

Сокрытие команд меню, кнопок и панелей

Сокрытие команды меню Сервис —»Windows Update

К л ю ч :

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Curren

tVersion\Policies\Explorer]

Значение:"NoWir.dowsUpdate"=dword: 00000001

Сокрытие команды меню Файл -» Создать

Ключ:[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Curren

tVersion\Policies\Explorer]

Значение:"NoExpandedNewMenu"=dword:00000001

Page 188: Delphi учимся на примерах

Настройка браузера Internet Explorer 187

Сокрытие команды меню Файл —> Сохранить как

Ключ:

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Curren

tVersion\Policies\Explorer]

Значение:

"NoBrowserSaveAs"=dword:00000001

Сокрытие кнопки Настройка в панели Поиск

Ключ:

[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Inter

net Explorer\Restrictions]

Значение:

"NoSearchCustomization"=dword:00000001

Сокрытие раздела Избранное

Ключ:

[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Inter

net Explorer\Restrictions]

Значение:

"NoFavorites"=dword:00000001

Сокрытие команды меню Сервис —» Почта и новости

Ключ:

[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Inter

net Explorer\Restrictions]

Значение:

"RestGoMenu"=dword:00000001

Сокрытие команды меню Сервис -» Свойства обозревателя

Ключ:

[HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Inter

net Explorer\Restrictions]

Значение:

"NoBrowserOptions"=dword:00000001

Сокрытие кнопки Сертификаты

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Page 189: Delphi учимся на примерах

188 Справочник по реестру Windows

Значения:

"CertifPers"=dword:00000001

"CertifSite"=dword:00000001

Сокрытие элементов окна Свойства обозревателя

Сокрытие вкладки Общие

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control- Panel]

Значение:

"GeneralTab"=dword:00000001

Сокрытие вкладки Безопасность

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"SecurityTab"=dword:00000001

Сокрытие вкладки Содержание

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"ContentTab"=dword:00000001

Сокрытие вкладки Подключение

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"ConnectionsTab"=dword:00000001

Сокрытие вкладки Программы

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

Page 190: Delphi учимся на примерах

Настройка браузера Internet Explorer 189

"ProgramsTab"=dword:00000001

Сокрытие вкладки Дополнительно

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"AdvancedTab"=dword:00000001

Сокрытие кнопки Сброс настроек для Web

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"ResetWebSettings"=dword:00000001

Отключение возможности производить изменения на вкладке

Дополнительно

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"Advanced"=dword:00000001

Общая настройка браузера

Отключение возможности перехода к домашней странице

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"HomePage"=dword:00000001

Отключение возможности управления временными файлами

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:"Settings"=dword:00000001

Page 191: Delphi учимся на примерах

190 Справочник по реестру Windows

Отключение возможности изменения настроек для временных файлов

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"Cache"=dword:00000001

Отключение возможности изменения настроек журнала истории

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"History"=dword:00000001

Отключение возможности изменения цветовых настроек на страницах

с неявным заданием цветов

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"Colors"=dword:00000001

Отключение возможности изменения цветовых настроек на HTML-

странице

Ключ:

[HKEY_CURRENT__USER\Software\Policies\Microsoft\Intern

et ExplorerVControl Panel]

Значение:

"Links"=dword:00000001

Отключение возможности изменения шрифта на страницах с неявным

заданием шрифта

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:"Fonts"=dword:00000001

Page 192: Delphi учимся на примерах

Настройка браузера Internet Explorer 191

Отключение возможности изменения языковых настроек

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"Languages"=dword:00000001

Отключение возможности изменения стилей

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"Accessibilitу"=dword:00000001

Отключение возможности изменения уровня безопасности

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"SecChangeSettings"=dword:00000001

Отключение возможности изменения сертификатов

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:

"Certificates"=dword:00000001

Отключение возможности автозаполнения для форм

Ключ:

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Значение:"FormSuggest"=dword:00000001

Запрет на заполнение имен и паролей на формах

Ключ:[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]

Page 193: Delphi учимся на примерах

192 Справочник по реестру Windows

Значение:"FormSuggest Passwords"=dword:00000001

Отключение возможности запуска мастера подключения к Internet

Ключ:[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et ExplorerXControl Panel]Значение:"Connwiz Admin Lock"=dword:00000001

Отключение возможности настройки подключения к Internet

Ключ:[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et Explorer\Control Panel]Значение:"Connection Settings"=dword:00000001

Отключение возможности автонастройки

Ключ:[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et ExplorerXControl Panel]

Значение:"AutoConfig"=dword:00000001

Отключение возможности настройки прокси-сервера

Ключ:[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et ExplorerXControl Panel]Значение:"Proxy"=dword:00000001

Отключение возможности изменения опции Проверять, является лиInternet Explorer обозревателем, используемым по умолчаниюК л ю ч :[HKEY_CURRENT_USER\Software\Policies\Microsoft\Intern

et ExplorerXControl Panel]Значение:"Check If Default"=dword:00000001

Page 194: Delphi учимся на примерах

Настройка браузера Internet Explorer 193

Установка адреса поискового сервера по умолчанию

Ключ:

[HKEY_CURRENT_USER\Software\Microsoft\Internet Ех-

plorer\Main]

Значение:"Search Page"=http://www.ya.ru

13 — 5-1212

Page 195: Delphi учимся на примерах

194 Язык Object Pascal

Приложение Г

Язык Object Pascal

КомментарииКомментарии — это фрагменты исходного текста программы, ко-

торые не компилируются и служат для пояснения кода. Для обозначе-ния комментариев в программах на языке Object Pascal используют сле-дующие конструкции:

• / / — комментарии в одной строке;• { } или (* *) —многострочные комментарии.

1 := i + 1; // увеличиваем на единицу счетчикs := IntToStr ( i ) ; {используем функцию IntToStr , которая

возвращает- строковое представлениецелочисленного параметра}

ИдентификаторыИдентификаторы - - это имена констант, переменных, типов,

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

В языке Object Pascal идентификаторы не чувствительны к региструбукв, то есть нет различия между строчными и заглавными буквами. Та-ким образом, идентификатор функции IntToStr равнозначен иденти-фикатору i n t t o s t r или intTOstr .

В качестве имен идентификаторов не могут использоваться сле-дующие зарезервированные слова: .

• and, array, as, asm, at, automated;• begin;• case,class, const, constructor;

• destructor, div, do, downto;

• else, end, except, exports;

Page 196: Delphi учимся на примерах

Встроенные типы данных 195

• file,finalization,finally, for, function;

• goto;

• if, implementation, in, inherited, initialization,

inline, interface, is;

• label, library;

• mod;

• nil, not;

• object, of, on, or, out;

• packed, private, procedure, program, property, pro-

tected, public, published;

• raise,record, repeat, resourcestring;

• set, shl, shr, string;

• then, threadvar, to, try, type;

• unit, until, uses;

• var;

• while, with;

• xor.

Встроенные типы данных

Числовые типы

К числовым типам языка Object Pascal относятся целочисленные итипы чисел с плавающей запятой (табл. Д.1).

Таблица Д.1. Числовые типы данных языка Object Pascal

Целочисленные

типы

Byte

Shortlnt

Smalllnt

Word

Integer,

Longlnt

Cardinal,

LongWord

Int64

Диапазон

значений

0..255

-128..127

-32768..32767

0..65535

-2147483648..

21474883647

0..4294967295

-263..263-1

Типы чисел с

плавающей запятой

Real

Real48

Single

Double

Extended

Comp

Currency

Диапазон значений

5.0-10' 3 2 4 . . 1.7-103 0 8

2.9-10"3 9.. 1.7-1038

1.5-10~ 4 5..3.4-10 3 8

5.0-10- 3 2 4 . . 1.7-103 0 8

3.6-10" 4 9 5 1 . . 1.1-104 9 3 2

- 2 6 3 + 1 .. 2 6 3 - 1

-922337203685477.5808..

922337203685477.5807

13*

Page 197: Delphi учимся на примерах

196 Язык Object Pascal

Символьный тип

Символьный тип обозначается при помощи ключевого слова Charи его значения хранят только один символ.

Строковые типы

В языке Object Pascal используются два обобщенных строковых типа:• S t r i n g — если в проекте Delphi указана директива компиля-

тора {$н+} (поддержка больших строк), то этому типу соот-ветствуют строки длиной от 0 до 2147483648 символов; впротивном случае типу String соответствуют строки длинойот 0 до 255 символов;

• PChar — тип, аналогичный строковому типу языка С.

По своей сути, строковые значения — это массивы символов, в ко-торых нумерация элементов для типа S t r i n g начинается с 1, а для типаPChar — сО.

Булев тип данных

Переменная булевого типа занимает один байт памяти и может при-нимать только одно из двух значений: True ("истина", "да", 1) илиFalse ("ложь", "нет", 0). Булев тип обозначается при помощи ключево-го слова Boolean.

Массивы

Массив — это упорядоченная именованная совокупность однотип-ных значений, к которым можно обращаться по их порядковому номеру(индексу). Для описания массивов в языке Object Pascal используютследующие формы:

• a r r a y [ 1 . .N1] of type — одномерный массив фиксиро-ванного размера (Ш — размерность массива, type — тип зна-чений, хранимых в массиве);

• a r r a y [ 1 . . N 1 , 1..N2] of type — двухмерный массивфиксированного размера;

• a r r a y [ 1 . . N 1 , 1..N2, 1..N3] o f type - - т р е х м е р н ы ймассив фиксированного размера;

• a r r a y of type — массив переменного размера. Длину та-ких массивов можно изменять в процессе выполнения про-

Page 198: Delphi учимся на примерах

Константы 197

граммы при помощи процедуры SetLength. Индексациязначений начинается с 0.

КонстантыКонстанта — это именованное фиксированное значение. Для объ-

явления констант используют конструкцию вида:const имя_константы = значение;

const Factor = 1.756;

Тип константы определяется автоматически по присвоенному ейзначению.

ПеременныеПеременная — это именованное значение определенного типа, ко-

торое можно изменять в процессе выполнения программы. Для объяв-ления переменных используют запись следующего вида:

v а г имя_ переменной: имя_ типа ;

vari: Integer; //переменная i типа Integers: String; //переменная S типа StringMyArray: array[1..10] of Char; {переменная MyArray — массив

значений типа Char. Эту переменную можнобыло бы также объявить как StringflO]}

При обращении и инициализации переменных используют следую-щие правила:

• для присвоения значений переменным используют операторприсваивания : =;

• строковые и символьные значения, присваиваемые перемен-ным, заключают в одинарные кавычки (' с ' , ' строка');

• для обращения к отдельным элементам массива или отдель-ным символам строки используют запись вида: а [ 1 ] - - дляодномерных массивов и строк; а [ 3 ] [ 1 ] - - для двухмерныхмассивов; а [ 1 ] [ 6 ] [ 2 ] — для трехмерных массивов и т. д.;

• в качестве типа переменной может быть указан как встроен-ный тип языка Object Pascal, так и пользовательский, опреде-

Page 199: Delphi учимся на примерах

198 Язык Object Pascal

ленный при помощи ключевого слова type (создание поль-зовательских типов рассматривается ниже).

К переменным в программе обращаются по их идентификаторам.

Пример для типа Str ing :var

si, s2: String; //объявляем две переменные типа Stringс: Char; //и одну типа Char

si := 'Строка'; //присваиваем si некоторое значениес := s[l]; //переменная с хранит значение 'Сs2 := si + с; //в s2 сохраняем строку 'СтрокаС'

Пр_имер для динамического массива:var

MyArray: array of Char;s: String;

SetLength(MyArray, 1 ) ; //устанавливаем длину массива = 1

A [ 0 ] : = ' С ' ;SetLength(MyArray, 2 ) ; //устанавливаем длину массива = 2А [ 1 ] : = ' т ' ;s := А[0] + А[1] + 'рока' //в s сохраняется значение 'Строка'

Пользовательские типы данныхДля объявления пользовательских типов, используют конструкцию

вида:type имя_типа = описание^типа;

К примеру, таким образом можно объявлять типы множеств, пере-числимые типы и подтипы.

Множества

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

set of первое_значение..последнее_значение;

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

Page 200: Delphi учимся на примерах

Пользовательские типы данных 199

Например:t y p e

TNumbers = s e t o f 1 . . 1 0 ;

T A l p h a b e t = s e t o f ' a 'v a r

Odds, E v e n s : TNumbers;ABC: TAlphabet ;

j Odds := [ 1 , 3, 5, 7, 9] ;\ Evens := [2, 4, 6, 8, 1 0 ] ;

ABC := [ ' a ' , ' b ' , ' с ' ] ;

Перечислимые типы

Перечислимые типы используют для определения упорядоченныхнаборов значений в виде списка идентификаторов, соответствующихэтим значениям. Для объявления таких типов используют запись сле-дующего вида:

type имя типа = (элемент!, . . ., элемента);

По умолчанию, первому элементу соответствует число 0, второ-му — 1 и т.д. Для того чтобы сопоставить с каким-либо элементом дру-гое значение, следует использовать запись вида элемент = число.

Для извлечения числа, соответствующего некоторому элементу, ис-пользуется функция Ord.

ПримерtypeTDigits =

TConstantsvar

x: TDigits

(Zero, One,Six, Seven= (a = 10,

;k: TConstants;MyResult:

k := b; //kif x = ZeroMyResult :=

integer;

присваиваем

then k := a

Two, Three, Four, Five,Eight,

b = 3);

значении

//если

Ord(k); //MyResult

Nine, Ten);

3x=0, то к присваиваем 103 или 10

1

Page 201: Delphi учимся на примерах

200 Язык Object Pascal

Подтипы

Подтип определяет некоторый диапазон целочисленных или сим-вольных значений. Для его объявления используют запись вида:

type имя_типа = начало..конец;

Переменные этого типа не могут принимать значений вне указанно-

; typeTDigits = (Zero, One, Two, Three, Four, Five,

Six, Seven, Eight, Nine, Ten); //перечислимый типT123 = One..Three; //подтипTABC = 'A'..'С; //еще один подтип

vari: T123; //переменная I может принимать значения от 1 до 3с: ТАВС; // переменная с может содержать 'А', 'В' или 'С

ЗаписиЗапись - - это структурированный набор разнотипных элементов.

Отдельные элементы записи называются полями. Для объявления запи-си используется следующая конструкция:

record

поле!: тип;

полеЫ: тип;

end;

typeTCD = record //запись дляGroupYear:Title

end;

String;Integer;String;

var MyCD:TCD;

//поле,//поле,//поле,

храненияхранящеехранящеехранящее

i

данных о музыкальном CDназвание исполнителягод альбоманазвание альбома

|

или непосредственноvar MyCD: record

Group:Year:Title:

end;

String;Integer;String;

^ ^MyCD.Group := 'Название группы';

Page 202: Delphi учимся на примерах

Классы 201

I MyCD.Year := 2005;| MyCD.Title := 'Название альбома';

КлассыКласс — это структура, предназначенная для хранения данных (по-

лей и свойств), а также кода, обрабатывающего эти данные (методы).Поля, методы и свойства называют членами класса.

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

Для объявления класса используют конструкцию вида:type имя_класса = class{имя родительского_класса)

published{объявление опубликованных членов класса}

private

{объявление закрытых членов класса}

public

{объявление открытых членов класса}

protected

{объявление защищенных членов класса}

end;

Определение членов класса

Все члены класса по характеру доступа к ним делятся на четыре ка-тегории: закрытые (private), защищенные (protected), открытые (public) иопубликованные (published).

Элементы класса, определенные в разделе publ ic , без каких-либоограничений открыты для доступа извне программного модуля. Без ог-раничений доступны также и элементы, определенные в разделе pub-l i shed, однако они отличаются тем, что для них генерируется инфор-мация о типах времени выполнения (RTTI — Run Time TypeInformation). Информация RTTI используется для различных целей: на-пример, для организации отображения значений свойств в инспектореобъектов.

14 — 5 - 1 2 1 2

Page 203: Delphi учимся на примерах

202 Язык Object Pascal

Элементы, определенные в разделе p r i v a t e , недоступны за преде-лами программного модуля, в котором объявлен класс. Другими слова-ми, закрытые члены класса нельзя вызвать из другого модуля.

Элементы, определенные в разделе p r o t e c t e d , доступны в модуле,в котором объявлен класс, а также доступны всем членам классов, про-изводных от данного класса.

По умолчанию при создании программных модулей Object Pascalраздел p r o t e c t e d не создается, а раздел publ i shed не указывается яв-но. Все члены класса, которые не определены в разделах p r i v a t e иpubl ic , по умолчанию относятся к категории publ ished.

Рассмотрим, к примеру, фрагмент объявления класса TForm (мо-дуль Forms . pas), базовогоJJ£[£J}£PJlj[J]^^

TForm = class(TCustomForm)

publicprocedure Arrangelcons;procedure Cascade;

published

property Action;

property ActiveControl;

end;

В данном случае видно, что класс TForm является производным откласса TCustomForm (реализован в том же модуле Forms.pas) и со-держит открытые методы Arrangelcons, Cascade И Т.Д., а также опуб-ликованные свойства Action, ActiveControl и т.д.

ПримечаниеОбъявление класса и его членов осуществляется в разделе i n t e r f a c e про-граммного модуля, а непосредственная реализация свойств и методов — в разде-ле i m p l e m e n t a t i o n (структура программного модуля Object Pascal рассмат-ривается ниже).

Во всех модулях форм, автоматически создаваемых Delphi, можно

______________typeTForml = class(TForm)

private

{ Private declarations }

public

{ Public declarations }

end;

Page 204: Delphi учимся на примерах

Классы 203

!varFormi: TForml;

Это означает, что в модуле приложения объявлен класс TForml,производный от класса TForm, а затем объявлена переменная типаTForml. Такие переменные — экземпляры класса — называют объек-тами. Все компоненты Delphi — это объекты, экземпляры того или ино-го класса.

Свойства класса

Свойства — это именованные интерфейсы доступа к данным объ-екта. Например, у объекта класса TForm, есть свойства Height ("высо-та"), Width ("ширина"), Color ("цвет") и др. Присваивая свойствамзначения соответствующего типа, можно изменять внешний вид или ха-рактер поведения объекта.

Для доступа к свойствам объекта используется такая же конструк-

ция, как и для достугvar

Forml: TForml;

Forml.Caption :=Forml.Font.Color

ia к полям записи,

'Заголовок формы:= clWhite;

нап£им£р:

В данном случае, свойство Font ("шрифт") — это тоже объект клас-са TFont, у которого есть свойство Color ("цвет").

Такой же способ доступа используется и для всех компонентов, раз-1?щ£шше^?а^&°]£м^type

TForml = class(TForm)Editl: TEdit;

private{ Private declarations }

public{ Public declarations }

end;

var

Forml: TForml;

Forml.Editl.Text := '';

14»

Page 205: Delphi учимся на примерах

204 Язык Object Pascal

Методы класса

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

Для доступа к методам используется тот же подход, что и длясвойств:' Buttonl•Click; //вызов метода, реализующего нажатие клавиши I

КОНСТРУКЦИЯ w i t h - d o

Для упрощения программного кода при работе с записями и клас-сами в языке Object Pascal используется конструкция with-do. Напри-мер, фрагмент кода| MyCD.Group := 'Название группы';MyCD.Year :m 2005;

| MyCD.Title := 'Название альбома';! Forml.Caption := 'Заголовок формы';| Forml.Font.Color := clWhite;

можно записать в виде: ___| with MyCD dobegin

Group := 'Название группы';Year := 2005; „Title := 'Название альбома';

end;

with Forml dobegin

Caption := 'Заголовок формы';Font.Color := clWhite;

end;

Еще один вариант записи этого же фрагмента:with MyCD, Forml dobegin

Group := 'Название группы';Year := 2005;Title l

m 'Название альбома';

Caption :• 'Заголовок формы';Font,Color := clWhite;

end;

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

Page 206: Delphi учимся на примерах

Структура проекта Delphi 205

чтобы для объектов, указанных после слова with, не использовалисьполя, свойства или методы с одинаковыми названиями, поскольку этоможет привести к путанице.

Структура проекта Delphi

Проект Delphi состоит из файлов трех основных типов:• файл проекта с расширением . dpr;• программные модули форм — файлы с расширением .pas;• двоичные данные формы — файлы с расширением . dfm.

Файл . dfm Delphi формирует автоматически на основании значе-ний, присвоенных свойствам формы и размещенных на ней компонен-тов. Файлы .dpr и .pas также создаются Delphi автоматически, но вних можно вносить изменения вручную. Рассмотрим их структуру.

Файл проекта . dpr

Файл проекта Delphi — это, по сути, главный программный модуль,не связанный ни с какой формой. В нем указываются ссылки на про-граммные модули приложения и создаются формы. Он имеет следую-щеюprogram имя программы; //заголовок

//раздел, в котором указываются ссылки на модули формuses

Forms,

Unitl in 'Unitl.pas' {Forml}; //главная форма приложения//ссылки на остальные формы приложения

{$R *.res} {директива компилятора о подключениифайла ресурсов программы}

begin

//инициализация приложения как объектаApplication.Initialize;//создание главной формы приложенияApplication.CreateForm(TForml, Forml);//создание остальных форм//. . .

//запуск приложенияApplication.Run;

end.

Page 207: Delphi учимся на примерах

206 Язык Object Pascal

Перед словом begin можно добавлять объявления констант, типови переменных, а между словами begin и end — добавлять собственныйпрограммный код.

Файл программного модуля .pas

Файл программного модуля (формы или независимый) имеет сле-

j unit имя_модуля;

j //начало интерфейсной части модуляinterface

uses

{раздел ссылок на другие программные модули, классы,типы, переменные, процедуры или функции которыхиспользуются в данном модуле}

const

{описания констант}type

{описание типов, в частности — класса формы}var

{описание переменных, в частности - экземпляра формы}

//начало раздела реализации

implementation

uses

{раздел ссылок на другие программные модули}

{$R *.dfm) //директивы компилятора

const

{описания констант}type

{описание типов }var

{описание переменных }

{реализация процедур и функций модуля}end.

В интерфейсном разделе (между ключевыми словами i n t e r f a c e иimplementation) указываются элементы программного модуля, дос-

Page 208: Delphi учимся на примерах

Процедуры и функции 207

тупные для других модулей и программ, а также ссылки на другие мо-дули (раздел uses).

Все описания и операторы, помещаемые в раздел реализации (послеключевого слова implementation), доступны только внутри данногопрограммного модуля.

Процедуры и функцииПроцедура - - это именованный программный блок, который не

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

Синтаксис процедур:procedure имя_процедуры(список_параметрош) ;

{Локальные объявления констант,

типов и переменных}

begin

//Тело процедуры

end;

Синтаксис функций:function имя_процедуры(список_парамеярот):

тип_тозвращаемого_значения;

{Локальные объявления констант,

типов и переменных}

begin

//Тело функции

Result := возвращаемое_зна.чение;

end;

Параметры

Список параметров, передаваемых в процедуру или в функцию,имеет следующий синтаксис:

параметр1: тип; ...; параметры: тип

Если процедура или функция не принимает никаких параметров, тоее заголовок выглядит следующим образом:

procedure имя_процедуры;

Page 209: Delphi учимся на примерах

208 Язык Object Pascal

function иия_процедуры:тип возвращаемого__значения;

Те параметры, перед которыми при объявлении указано ключевоеслово var, называются параметрами, передаваемыми по ссылке. Этоозначает, что к значению этого параметра сохраняется доступ и послевыхода из функции или процедуры. Такие параметры можно использо-вать для возврата результата в процедурах или возврата более одногорезультата в функциях.

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

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

Вызов процедур и функций

Процедуры и функции вызываются по их названию с указанием в

s := IntToStr(i); //вызов функции IntToStr

delete (s, 1, 2); {вызов процедуры delete, которая удаляет изстроки s два символа, начиная с первого.В данном случае, переменная s являетсяпараметром, передаваемым по ссылке}

Если в процедуру или функцию не передаются никакие параметры(как во многих методах объектов), то вызов осуществляется только по

//вызов метода (процедуры) Click//вызов функции GetCurrentDir

Досрочный выход из процедуры или функции

Для досрочного выхода из процедуры или функции в ее теле следу-ет указать вызов процедуры Exit .

ОператорыОператор — это конструкция языка Object Pascal, выполняющая

определенную операцию. Все операторы можно разбить на несколькокатегорий.

Page 210: Delphi учимся на примерах

Операторы 209

Оператор присваивания

Слева от оператора присваивания : = указывается переменная илисвойство объекта, а справа — некоторое значение или выражение. Типзначения или результат выражения должен соответствовать типу пере-менной или свойства.

Арифметические операторы

Арифметические операторы возвращают значения, соответствую-щие типам числовых операндов:

• + — сложение;• вычитание;• * — умножение;• / — деление чисел с плавающей запятой;• div — целочисленное деление с отбрасыванием остатка;• mod — получение остатка от целочисленного деления.

Булевы операторы

Булевы операторы возвращают значения типа Boolean:• not — отрицание;• and — логическое "И";• or — логическое "ИЛИ";• хог — логическое исключающее "ИЛИ".

Операторы сравнения

Операторы сравнения возвращают значение типа Boolean:• = — равно;• <> — не равно;• < — меньше;• > — больше;• <= — меньше или равно;• >= — больше или равно.

Побитовые операторы

Побитовые операторы выполняют действия с операндами с учетомих двоичного представления:

• not — побитовое отрицание (not 0 = 1; not I = 0);• and — побитовое умножение (0 and N = 0; 1 and 1 = 1);

Page 211: Delphi учимся на примерах

210 Язык Object Pascal

• or — побитовое сложение (1 or N = 1; 0 or 0 = 0);• xor — побитовое исключающее сложение (0 xor 0 = 0; 0

xor 1 = 1; 1 xor 1 = 0);• sh l — побитовый сдвиг влево;• shr — побитовый сдвиг вправо.

Строковые операторы

Строковые операторы применяются к операндам строкового илисимвольного типа:

- • =, о , <, >, <=, >= — операторы сравнения;• + — оператор конкатенации (слияния операндов).

Операторы, применяемые к множествам

К множествам применяются следующие операторы:• + — объединение (результат — множество);• вычитание (результат — множество);• * — пересечение (результат — множество);• <= — подмножество (результат — множество);• >= — супермножество (результат — множество);• = — равенство (результат — значение типа Boolean);• о — неравенство (результат — значение типа Boolean);• in — вхождение множества, указанного слева от оператора,

во множество, указанное справа (результат — значение типаBoolean).

Операторы, применяемые с объектами

С объектами применяют следующие операторы:• as — приведение к производному классу. Пример использо-

вания:var Obj: TObject; //объект класса TObject

with Obj as TButton do //приводим к классу TButtonCaption := 'Кнопка'; //то же, что Obj.Caption

i s — сравнение с классом. Пример использования:var Obj: TObject; //объект класса TObject

if Obj is TButton then //если Obj - объект класса

//TButton, то...

Obj.Caption := 'Кнопка';

Page 212: Delphi учимся на примерах

Блоки программного кода 211

• =, <> — операторы сравнения.

Группировка операторов

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

Порядок выполнения операторов

В сложных выражениях операторы выполняются в следующем по-рядке:

1. ( )•

2. not.

3. *, /, div, mod, and, shl, shr, as.

4. +, -, or, xor.

5. =, <>, <, >, <=, >=, in, is.

Блоки программного кодаДва и более операторов присваивания, а также вызовов процедур

или функций можно выделять в блоки программного кода при помощиключевых слов begin и end. Такие блоки используются в конструкцииwith-do, а также в рассматриваемых ниже циклических конструкциях иконструкциях ветвления.

Конструкции ветвленияКонструкции ветвления осуществляют переход к одному из блоков

программного кода на основании проверки некоторого условия. К нимотносятся операторы i f и case.

Оператор if

Оператор i f имеет синтаксис двух видов:if выражение then блок^кода;if выражение then блок_кода else блок_кода;

Если выражение возвращает значение True, то выполняется блоккода, расположенный после ключевого слова then, в противном случаевыполняется или программный код, расположенный после конструкцииi f - t h e n (в случае отсутствия ветки else), или же код, расположенныйпосле ключевого слова e l s e . i

Page 213: Delphi учимся на примерах

212 Язык Object Pascal

Оператор case

Конструкция case используется для ветвления, когда может суще-ствовать более двух возможных результатов условного выражения.

Она также имеет синтаксис двух видов:case выражение of

значение!: блок_кода1;

значением: блок_кодаЫ;

end;

илиcase выражение of

значение!: блок_кодаЫ;

значением-. блок_кодаЫ;

else блок_кода;

end;

Если результат выражения совпадает со значением!, то выполня-ется блок^кода!; если со значением2 — 6лок_кода2 и т.д. Если ре-зультат выражения не совпадает ни с одним значением, то выполняетсяблок кода в ветке e l se , а при ее отсутствии — код после ключевогослова end, завершающего конструкцию case.

ПримечаниеРезультат выражения, который сопоставляется со значениями в ветках конструк-ции c a s e , может быть только целочисленного или символьного типа.

Циклические конструкцииДля организации циклического выполнения программных блоков в

языке Object Pascal используют циклические конструкции трех типов:for-do, while-do и r e p e a t - u n t i l . Они отличаются характером нача-ла и завершения цикла.

Конструкция for-do

Синтаксис конструкции for-do для цикла с увеличением значениясчетчика:

for идентификатор_счетчика := начальное_значение

Page 214: Delphi учимся на примерах

Обработка исключений 213

to конечное_эначение

do блок_кода;

Синтаксис конструкции f or-do для цикла с уменьшением значениясчетчика:

for идентификатор_счетчика := начальное_значение

downto конечное__значение

do блок_кода;

Выход из цикла for определяется достижениям некоторого значе-ния специальной переменной, называемой счетчиком цикла. Цикл вы-полняется как минимум один раз.

Конструкция vhile-do

Синтаксис конструкции while-do:while выражение do блок_кода;

Выход из цикла while-do происходит в том случае, если выраже-ние, расположенное между ключевыми словами while и do, дает значе-ние False. Цикл может не выполниться ни одного раза.

Конструкция repeat-until

Синтаксис конструкции repeat-unti l :repeat блок_кода unt i l выражение;

Выход из цикла r e p e a t - u n t i l происходит в том случае, если вы-ражение, расположенное после ключевого слова u n t i l , дает значениеTrue.

Досрочный выход из циклов

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

Обработка исключенийИсключение (exception) — это результат выполнения некорректно-

го оператора, что привело к возникновению ошибки. В языке ObjectPascal для обработки исключений предназначена специальная конст-рукция:

Page 215: Delphi учимся на примерах

214 Язык Object Pascal

—II try

//Операторы, которые могут привести к возникновению исклю-

• чения

! except

//Операторы, выполняемые в случае возникновения исключения

< end;

В случае возникновения исключения б блоке операторов, располо-женных между ключевыми словами t r y и except, управление переда-ется блоку операторов после слова except, где можно определить реак-цию на возникшую ошибку.

В частности, в блоке except можно обрабатывать исключения в за-висимости от их типа с помощью конструкцииj except

on Тип_исключения1 do Блок_операторов1;

on Тип_исключения2 do Блок_операторов2;

on Тип_исключенияЫ do Блок__операторовЫ;

end;

Типу исключения соответствует имя класса, производного от классаException. В отличие от других классов Delphi, имена классов исклю-чений начинаются к латинской буквы "Е". Перечислим некоторые изэтих классов:

• EZeroDivide — деление на ноль;• EAccessViolation — ошибка доступа к памяти;• ERangeError — выход значения за границы допустимого

диапазона;• EStackOverflow — переполнение стека памяти из-за слиш-

ком больших переменных или чрезмерно большого количест-во рекурсивных вызовов процедур (вызов процедуры самойсебя);

• EConvertError — ошибка преобразования (например, стро-ки в число);

• EDatabaseError — ошибка при работе с базой данных;• EOutOfMemory — переполнение памяти;• EFCreateError — ошибка создания файла;• E F i l e r E r r o r — ошибка чтения/записи при работе с файлом;• EFOpenError — ошибка открытия файла;• EIniFi leExcept ion — ошибка при работе с INI-файлом;• EInOutError — ошибка ввода-вывода.

Page 216: Delphi учимся на примерах

Обработка исключений 215

Если тип исключения точно неизвестен, то для его обработки мож-но воспользоваться следующей конструкцией: _____; except

on E: Exception do Бмок_операторов;end;

При этом в блоке операторов после ключевого слова do можно об-ращаться к свойству Е.Message, которое содержит строку с описаниемошибки.

Блок операторов finally

Существует еще одна конструкция, связанная с обработкой исклю-

ченийк_ _ _ _ _ _ _ _ „ _ _ _ _ _ _try

//Операторы, которые могут привести к возникновению//исключения

finally//Операторы, которые выполняются при любых условиях

end;

Блок операторов после ключевого слова f i n a l l y выполняетсяв любом случае, независимо от того, возникло исключение в блоке t r yили нет.

Page 217: Delphi учимся на примерах

ББК 32.973.26-018.1УДК 681.3.06

П18

Парижський С. М.П18 Delphi. Вчимося на прикладах/Пщ ред. Ю. О. Шпака - К.: "МК-

Прес", 2005.-216с, \п.

ISBN 966-8806-02-6

Ця книга — продовження попередньоТ книги автора, "Delphi. Ильки практика". Як iв "Delphi. "Пльки практика", в цьому виданж детально розглянуто програми для мереж,pi3HOMaHiTHi жарт1влив1 програми, прост! irpauiKn, деяю KopncHi приклади, розробка програмв CTHni Windows XP. Зокрема, тут можна знайти таю приклади як безкоштовна выправкаSMS, FTP-Miiem", просте шифрування, CGI-сценарм та багато Ышого. Описан|' методироботи з системним реестром Windows та INI-файлами, а також деяю важлив! аспектипрограмування на системному piBHi i3 застосуванням функц!й Windows API. Дляполегшення розумЫня програм кожний приклад мютить коментар1 складних рядюв коду.

Книга ор1ентована як на тих, хто вже мае досвщ створення програм в Delphi, так i напрограмюта-початювцчв Для тих хто ттьки починае використовувати Delphi, наприюнцчкниги е додаток з описом синтаксису мови програмування Object Pascal.

ББК 32.973.26-018.1

Парижський Серий Михайлович

DelphiВЧИМОСЯ НА ПРИКЛАДАХ

Головнип редактор: Ю. О. ШпакКомп'ютерна верстка: Ю. О. Шпак

Пщписано до друку 11.07.2005. Формат 60 х 84 1/16.flanip газетний. Друк офсетний. Ум. друк. л. 12,6. Обл.-вид. л. 6,9.

Тираж 2000 екз. Замовлення № 5-1212

ПП Савченко Л.О., УкраТна, м.КиТв, тел./ф.: (044) 517-73-77; e-mail: [email protected].Свщоцтво про внесения суб'екта видавничоТ справи до Державного реестру видавниюв,

вигот1вник1в та розповсюджувач1в видавничо!' продукцм: сер1я ДК №51582 вщ 28.11.2003р.

Надруковано в ЗАТ"В1ПОЛ". 03151, м.КиТв, аул. Волинська, 60

© Парижський С. М., текст, тюстрацм, 2005ISBN 966—8806—02—6 © "МК-Прес", оформления, дизайн обкладинки, 2005