Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

[ Миронченко ] Императивное и объектно-ориентированное програмирование на Turbo Pascal и Delphi

.pdf
Скачиваний:
68
Добавлен:
25.04.2014
Размер:
3.16 Mб
Скачать

321

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

1.Частота встречаемости букв

2.Знания о структуре слова

Наиболее часто используемые приставки, суффиксы и окончания

Часто используемые буквосочетания (например, сдвоенные буквы)

3.Частота встречаемости слов

Короткие слова

Избыточность языка (напр., артикли)

4.Структура предложения

Порядок слов в предложении

Стандартные конструкции (напр., вспомогательные глаголы при образовании времен)

Апострофы (после них или перед ними во многих языках могут стоять лишь некоторые буквы)

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

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

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

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

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

Некоторые подзадачи:

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

2.Источник знаний для работы со словами должен уметь:

Составлять список слов в тексте (разные словоформы одного слова считаются разными словами) вместе с их частотой встречаемости.

Сортировать этот список (список будет большой, поэтому алгоритм должен быть быстрый).

Искать в словаре заданное слово, и выдавать частоту встречаемости данного слова.

322

Поиск по маске Маска:

Любой элемент - ?

Не элемент - ~

Несколько элементов - *

Начало группы - {

Конец группы - }

Например, шаблон «?{a b d}?a~{s d e}» означает, что первая буква слова неизвестна, вторая – a, b или d, третья – неизвестна, четвертая – а, пятая – любая буква, не принадлежащая множеству {s, d, e}.

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

323

Глава 17: Визуальное программирование

Вы уже наверняка запустили стандартное оконное приложение, которое генерирует Delphi, и, быть может, перетащили на него несколько кнопок или текстовых полей. Теперь пришло время разобраться, как функционируют оконные приложения и как на них реагирует ОС.

17.1. Оконные приложения в Windows

Операционные системы могут полностью скрывать аппаратуру, либо напротив, предоставлять программам возможность прямого доступа к аппаратному обеспечению (АО). Windows XP полностью скрывает АО, а Windows 95 и 98 – дают возможность прямого доступа к АО. В дальнейшем будем рассматривать ОС, которые скрывают аппаратуру.

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

То, что мы можем с помощью Win32 API-функций работать с устройствами – это понятно, однако часто надо, чтобы сигналы от устройств влияли на работу приложений. Простейший пример этому – щелчок на кнопке. Раньше мы никогда не сталкивались с подобной ситуацией: мы могли сказать пользователю ввести некоторые данные, но если мы его не просим, то он может нажимать на кнопки сколько угодно – толку от этого все равно никакого. Зависимость приложения от сигналов, посылаемых внешними устройствами может быть реализована лишь с помощью ОС (т.к. она берет на себя всю работу с аппаратурой).

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

Когда какое-то устройство, например, мышь, посылает сигнал в ОС (например, что она переместилась вправо на столько-то пикселей), то ОС принимает этот сигнал и создает сообщение, которое она посылает приложению. В оконном приложении есть специальная функция («оконная функция»), которая может принимать эти сообщения и, при надобности, их обрабатывать. Например, если пользователь щелкнул левой кнопкой мышки в области окна, мышь сообщит ОС о том, что была нажата ее левая кнопка, а та вышлет сообщение WM_LEFTBUTTONDOWN, которое говорит приложению, содержащему это окно, о том, что была нажата левая кнопка мыши, а приложение уже само разбирается, какой смысл этому надо придать.

Многие важные сообщения, посылаемые ОС приложению, приводят к событиям – реакциям на сообщения ОС.

Если программное обеспечение (ПО) построено таким образом, что на его работу могут влиять события, то такое ПО называется событийно-управляемым.

Для того, чтобы упростить разработку визуальных приложений, добиться единства интерфейса в прикладных программах и ускорить работу самих приложений, в Windows разработан GUI (Graphic User Interface) – набор подпрограмм, которые

324

позволяют создавать окна, кнопки, меню, списки и т.д. Все эти подпрограммы тоже входят в состав Win32 API.

17.2.Cоздание оконных приложений в Delphi

ВDelphi создавать оконные приложения очень просто. Во-первых, у каждого оконного приложения есть специальный объект Application (англ. приложение) класса TApplication, который берет на себя обработку сообщений от Windows. У этого класса есть метод Run, основную часть которого составляет цикл, в котором он обрабатывает сообщения Windows.

Во-вторых, встроенная среда разработки показывает список компонентов (компонент – это любой наследник класса TComponent стандартной библиотеки классов), которые можно просто перетаскивать на форму (окно).

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

Метод, вызывающийся при возникновении события, называется обработчиком события.

Основным компонентом является форма, на которой размещаются остальные компоненты. Форма – это любой наследник класса TForm. Сам класс TForm инкапсулирует все необходимое (с точки зрения разработчиков Delphi) для работы с пустым окном – его можно перемещать, изменять размеры, сворачивать, восстанавливать и т.д.

17.3. Первое оконное приложение

Теперь создайте приложение с формой (при создании нового приложения выберите VCL Forms Application для Win32 (в версиях Delphi 6,7 – просто Application) , а не Console Application, как мы делали ранее).

Давайте разберемся с программным кодом. Нажав на Code, вы увидите вспомогательный модуль. Для того, чтобы открыть основную программу и остальные файлы с программным кодом, связанные с вашим проектом (так называется приложение в Delphi), вы можете просто нажать Ctrl+F12 (или нажать соответствующую кнопку – она находится слева от кнопки запуска программы.

Нажмите Ctrl+F12, и откройте файл Project1 (так по умолчанию называется проект). Это и есть основная программа.

Итак, простейшая программа состоит из 2-х файлов: основного и вспомогательного модуля, в котором находится форма.

Пример 1: Простейшая программа.

-------------------- файл Project1.dpr ------------------------

1 : program Project1;

2 :

3 : uses

4 : Forms,

5 : Unit1 in 'Unit1.pas' {Form1};

6 :

7 : {$R *.res}

8 :

325

9 : begin

10:Application.Initialize;

11:Application.CreateForm(TForm1, Form1);

12:Application.Run;

13:end.

---------------------- файл Unit1.pas --------------------------

1 : unit Unit1;

2 :

3 : interface

4 :

5 : uses

6 : Windows, Messages, SysUtils, Variants, Classes, Graphics,

7 : Controls, Forms, Dialogs;

8 :

9 : type

10:TForm1 = class(TForm)

11:private

12:{ Private declarations }

13:public

14:{ Public declarations }

15:end;

16:

17:var

18:Form1: TForm1;

20:implementation

22:{$R *.dfm}

24:end.

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

TForm.

Во вспомогательном модуле описан один класс – TForm1, являющийся наследником TForm (правда, ничем не отличающимся от своего родителя), а также объект Form1 этого класса.

С помощью директивы {$R *.dfm} подключаются файлы, связанные с формами. В основном файле проекта с помощью

{$R *.res}

подключаются файлы ресурсов, связанные с проектом.

В трех строках в инициализирующей части вызываются три метода для глобального объекта Application класса TApplication. Метод Initialize выполняет вспомогательные функции, метод CreateForm инициализирует форму начальными значениями (в этот метод передается класс, которому принадлежит форма и сам объект-форма, следовательно, первый параметр метода CreateForm класса Application – это метакласс).

Метод Run запускает оконное приложение.

326

Форма должна быть в находиться в отдельном pas-файле. В придачу к этому pasфайлу будет создан одноименный файл с расширением dfm, в котором будут храниться параметры настройки формы.

17.4. Добавляем компоненты на форму (пример № 2)

Создайте новое приложение (VCL Forms Application), затем найдите в наборе компонентов во вкладке Standard следующие 2: текстовое поле (TMemo) и кнопку

(TButton).

Щелкнув по компоненту дважды, вы добавите его на форму. После этого его можно перемещать по форме и изменять его размеры.

Создайте форму, как показано на рис. 17.1.

В программном коде у формы добавится 2 поля:

TForm1 = class(TForm) Button1: TButton; Memo1: TMemo;

private

{Private declarations } public

{Public declarations }

end;

Рис 17.1 Форма для примера № 2

Запустите теперь программу и посмотрите, что теперь можно с ней делать.

Вы можете писать что-то в текстовом поле; можно нажимать на кнопку, хотя при этом ничего не происходит.

Кнопка и текстовое поле содержат ряд свойств, значения которых можно изменять. Самый простой способ сделать это – использовать Object-Inspector.

На рис. 17.2 изображен инспектор объектов (ИО) с краткими объяснениями. Вы можете выбрать в инспекторе объектов интересующий вас компонент и вы увидите свойства, которые есть у этого объекта. После этого просто в правой половине таблицы вы можете изменять значения этих свойств.

Измените заголовок формы (в ИО он называется Caption). Измените название на любое, которое вам нравится.

327

Выбор объекта Свойства

Объекта

События, на

которые может

реагировать Заголовок объект формы

Здесь можно

изменить

заголовок

формы

Рис. 17.2 Инспектор объектов

Теперь в качестве объекта выберите кнопку. Измените у нее название (Name) на Knopf. Можете изменить и название текстового поля с Memo1 на иное.

Давайте изменим начальное содержимое текстового поля. Для этого надо сделать следующие действия: найдите свойство Lines класса TStrings у объекта Memo1:

Теперь нажмите на маленькую кнопку с тремя точками. В окне, которое появится на экране вы сможете изменить текст.

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

Для этого дважды щелкните по кнопке. Оболочка Delphi сразу же добавит к форме следующий метод:

procedure TForm1.KnopfClick(Sender: TObject); begin

end;

У этого метода лишь 1 параметр, - объект, который отослал сообщение о событии. В данном случае Sender – сама кнопка.

Внутри этой процедуры допишите 1 строку, чтобы получилось следующее:

procedure TForm1.KnopfClick(Sender: TObject); begin

Form1.TextPlatz.Lines.Add('Вы нажали кнопку'); end;

328

TextPlatz – название текстового поля (если вы придумали другое название, то поставьте его вместо TextPlatz).

Внутри TextPlatz есть свойство Lines, в котором есть метод Add, которая добавляет строку, которая передана этой функции в текстовое поле. Поэтому строка 'Вы нажали кнопку' будет дописываться в текстовое поле после каждого нажатия на кнопку Knopf.

Как видите, мы написали лишь одну строчку кода, а наша программа уже содержит кнопки, текстовые поля, и т.д. Это, конечно, не идет ни в какое сравнение с ТР, в котором надо было практически все делать самому. Но такое «программирование интерфейса», блуждания по меню и установка начальных свойств – дело необычайно нудное и глупое. Поэтому вы можете возмутиться тем, что после стольких проектов вы должны заниматься такой ерундой:

Тяжелая доля досталась герою; вождю довелось зерна молоть! Руке той привычна меча рукоять, а вовсе не палка,

что жернов вращает.

Старшая Эдда. Вторая песнь о Хельги убийце Хундинга

Однако написание всех методов «руками» - тоже занятие весьма глупое, поэтому почему бы не сэкономить себе время там, где это можно, а затем заняться более подобающим делом, как и Хельги, который славными подвигами покрыл свое имя, и после смерти стал править Вальхаллой вместе с Одином.

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

17.5. Убегающая кнопка. Обработка события OnMouseMove (пример № 3)

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

Inspector, вкладка Events.

Нажатие на кнопку – это событие OnClick. Процедура, в которой задаются действия в ответ на событие, называется обработчиком события. В предыдущей программе мы научились создавать обработчик события OnClick. Для этого мы 2 раза нажимали на кнопке, и система самостоятельно создавала заголовок обработчика сообщения. Если вы теперь откроете тот проект, и для объекта Knopf откроете в Object Inspector вкладку Events, то вы увидите, что в поле OnClick стоит имя процедуры, которая была создана системой разработки.

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

329

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

Форма должна иметь следующий вид (шрифт надписей можете выбирать по вашему желанию):

Рис 17.3. Форма для примера №3

В начале работы программы надписи «Да! Жить хорошо и жизнь хороша»и «Чтото в программе не заладилось» должны быть невидимы и появляться лишь после нажатия на соответствующую кнопку.

Для создания надписей служит компонент Label. Создайте 3 таких компонента, а также 2 кнопки. После того, как вы создадите 3 Label, вы увидите, что надо еще изменить сам текст надписи, шрифт и размер. Вы уже знаете, что все эти свойства можно изменить в Object Inspector’е. Надпись – в раделе Caption, а шрифт и его размер можно изменить в свойстве

Нажмите на кнопку с тремя точками и откроется диалог, в котором вы сможете настроить необходимые параметры.

Если вы это сделали, идем дальше.

Надо сделать обе метки (кроме вопроса) невидимыми. Для этого задайте свойствам Visible (англ. видимый) этих двух компонентов значение False.

Теперь надо не дать пользователю нажать кнопку «Нет». Пользователь может нажать кнопку двумя способами:

1.нажав клавишу Enter, когда фокус ввода находится на кнопке. Например, на следующем рисунке фокус ввода находится на кнопке «Да, очень». Для того, чтобы фокус ввода перемещать с одного компонента на другой, можно просто нажимать Tab. Вы можете сами проверить это: надо лишь создать пустую форму, поместить на ней 2 кнопки и запустить программу.

2.с помощью мыши. Для этого надо поместить курсор над кнопкой и затем щелкнуть.

330

Чтобы не дать пользователю нажать на Enter, можно при запуске фокус ввода установить на кнопке «Да, очень», и запретить перемещать курсор на кнопку «Нет». Этого можно добиться так:

Зайдите в Object Inspector, выберите кнопку «Нет» (я в примере дал ей имя Nein), и найдите 2 свойства: TabOrder и TabStop. TabOrder устанавливает порядок обхода компонентов. Его значение может меняться в следующем диапазоне -1..32767.

-1 – это особый случай, и мы его рассматривать не будем.

0 – это означает, что при запуске фокус ввода будет именно на нем. С помощью Tab мы можем перейти от 0-го к 1-му компоненту и т.д.

Однако если мы установим свойству Tabstop кнопки Nein значение False, то к ней нельзя будет добраться с помощью клавиши Tab.

Теперь самое главное. Надо научиться перемещать кнопку, как только пользователь наведет на нее курсор мыши. Это сделать очень просто, потому что свойства компонентов можно изменять в процессе работы программы. Когда указатель мыши становится на кнопку, возникает событие OnMouseMove. Мы должны его обработать, т.е. описать, что должна делать программа в ответ на его возникновение. Для этого выберите кнопку Nein в Object Inspector’e и зайдите во вкладку Events. Там найдите событие OnMouseMove, и напишите название процедуры-событиеобработчика NeinMove. После этого будет создан пустой обработчик события. Надо лишь записать туда нужный код.

Координаты кнопки, как и других видимых компонентов, определяются следующими свойствами:

(Left, Top) – координаты верхнего левого угла кнопки. Height - высота, Width – ширина. Сам текст обработчика прост. В качестве параметров передаются координаты курсора мыши в тот момент, когда он оказался над кнопкой.

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

Пример 3: Убегающая кнопка.

1 : unit Haupt;

2 :

3 : interface

4 :

5 : uses

6 : Windows, Messages, SysUtils, Variants, Classes, Graphics,

7 : Controls, Forms, Dialogs, StdCtrls;

8 :

9 : type

10:TForm1 = class(TForm)

11:Ja: TButton;

12:Label1: TLabel;

13:Nein: TButton;

14:Label2: TLabel;

15:Label3: TLabel;

16:procedure JaClick(Sender: TObject);

17:procedure NeinClick(Sender: TObject);

18:procedure NeinMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);

19:private