программирование :: delphi

От Delphi 4 к Delphi 5 часть 15



От Delphi 4 к Delphi 5 Палитра компонентов.

Страница DIALOGS.

Windows поддерживает ряд стандартных диалоговых окон, позволяющих вам открывать файл, выбирать шрифт для заголовков компонентов, настраивать принтер, производить печать и т.д. Рассмотрим страницу Dialogs (рисунок 1), которая одинакова для Delphi 4 и Delphi 5 .

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

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

Компонент OpenPictureDialog (открыть рисунок) реализует стандартное окно выбора графических файлов с возможностью предварительного просмотра рисунков.

Компонент SavePictureDialog (сохранить рисунок) реализует специальное окно сохранения графических файлов с возможностью предварительного просмотра рисунков.

Компонент FontDialog (шрифт) реализует стандартное диалоговое окно выбора шрифта.

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

Компонент PrintDialog (печать) реализует стандартное диалоговое окно выбора параметров для печати документа.

Компонент PrintSetupDialog (настройка принтера) реализует стандартное диалоговое окно для настройки печатающего устройства.

Компонент FindDialog (поиск) реализует стандартное диалоговое окно поиска текстового фрагмента.

Компонент ReplaceDialog (замена) реализует стандартное диалоговое окно поиска и замены текстового фрагмента.

Переменные и указатели.

Перед изучением основ объектно-ориентированного программирования рассмотрим, что происходит при объявлении переменных, и что означает ссылка одной переменной на другую.

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

Каждый участок имеет свой номер. Среда Windows управляет памятью и содержимым регистров самостоятельно.

При запуске вашего приложения происходит обращение к участкам памяти с использованием адреса.

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

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

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

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

procedure TForm1.FormCreate(Sender: TObject); var I:Integer; PS:^Integer; begin I:=15; PS:=@I; end; end.

В данном примере переменная I целого типа, она содержит число 15. Переменная PS ввиду того, что перед словом имеется знак ^ , является переменной, содержащей адрес целой переменной.

Т.е. переменная PS в данной программе является переменной, содержащей адрес любой переменной целого типа.

Если посмотреть содержимое переменной PS, то увидим, что ее значение – это адрес целочисленной переменной. Что такое целочисленная переменная?

Строка PS:=@I; означает, что вы получаете адрес переменной I и сохраняете его в переменной PS. Другими словами, вы заставляете PS указывать на I.

При традиционном программировании данные находятся в одном месте программы, а процедуры, обрабатывающие эти данные, — в другом. Программистам необходимо много работать, чтобы осуществить связь процедур и данных.

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

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

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

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

Сущность объектно-ориентированного программирования.

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

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

Основанная на компонентах архитектура Delphi была бы невозможной, если бы не было объектов. Компоненты Delphi являются, по существу, специализированными объектами, и их функционирование определяется объектно-ориентированной архитектурой библиотеки визуальных компонентов (Visual Component Library – VCL).



Концепция объекта является ключом к пониманию объектно-ориентированного программирования. ООП использует объекты как строительные блоки (рисунок 2). Посмотрите внимательнее и запомните эту структуру.

Объект – это активная единица данных, которая представляет собой комбинацию как элементов данных, так и операций с этими данными, упакованных вместе для удобства использования.

Таким образом, объект объединяет данные и программный код.

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

Как источник действий, объект является набором методов, т.е. подпрограмм, разработанных для операций с полями. Все методы определяют его поведение.

Объект обладает свойствами, представляющими собой высокоуровневые атрибуты данных, которые тесно связаны с соответствующими методами доступа к данным.

Классы и объекты.

Все объекты объединены в классы.

Поведение объекта описывается определением его класса, т.е. он является представителем какого-либо класса. Таким образом, дадим следующее определение. Объект – это экземпляр класса или, другими словами, переменная того типа данных, который определен классом.

Итак, идем дальше.

Класс – термин, описывающий структурированный тип данных языка Object Pascal , определяющийся ключевым словом class.

Такое понятие дает возможность использовать набор общих характеристик отдельных групп объектов и разрабатывать конкретные реализации, которые позволяют всем объектам вести себя в соответствии с этими характеристиками.

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

Однако класс не отвечает за уничтожение объектов, они уничтожаются, когда вызывается соответствующий метод.

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

Итак, мы подошли к следующему положению.

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

Все классы Object Pascal порождены от единственного родителя класса TObject.

Он не имеет полей и свойств, но включает в себя методы самого общего назначения, обеспечивающие весь жизненный цикл любых объектов – от их создания до уничтожения.



Библиотека VCL описывает ряд подклассов класса TObject. Используя инструмент Browse Objects, можно просмотреть иерархическую структуру системы. Для этого необходимо запустить Delphi . Затем, используя главное меню, выбрать команду View, из раскрывшегося списка выбрать команду Browse — и иерархическая структура системы перед вами (рисунок 3).



Принцип наследования приводит к созданию ветвящегося дерева классов, постепенно разрастающегося от TObject к его потомкам (рисунок 4). Просматривая дерево классов, вы видите, что все компоненты Delphi порождены от класса TСomponent, в котором объединены самые общие свойства и методы компонентов. Предком TСomponent является класс TPersistent, который произошел непосредственно от базового класса TObject.

Обратите внимание на следующее.

Класс TComponent служит базой для создания как видимых, так и невидимых компонентов. Большинство видимых компонентов происходят от класса TControl. Два наследника этого класса – TWinControl и TGraphicControl — определяют две группы компонентов: имеющие оконный ресурс ( TWinControl и его потомки) и не имеющие оконного ресурса ( TGraphicControl и его потомки). Оконный ресурс – это специальный ресурс Windows, который предназначен для создания и обслуживания окон. Только оконные компоненты способны получать и обрабатывать сообщения Windows. Такой компонент в момент своего создания обращается к Windows с требованием выделения оконного ресурса и, если требование удовлетворено, получает так называемый дескриптор окна. TWinControl и его потомки хранят его в свойстве Handle. Программист может использовать этот дескриптор для непосредственного обращения к API – функциям Windows. Потомки TGraphicControl не требуют от Windows дефицитного оконного ресурса, но они и не могут получать и обрабатывать Windows- сообщения. Управляет такими элементами оконный компонент-владелец (например, форма), который является посредником между Windows и не оконными компонентами.

Классы могут быть связаны между собой разными способами. Одна из концепций объектного программирования – это понятие наследования классов, устанавливающее между двумя классами отношения "родитель – потомок".

Наследование – это способность одного класса использовать характеристики другого.

Предок – это класс, предоставляющий свои возможности и характеристики другим классам через механизм наследования.

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

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

Используя Object Pascal, вы можете легко определять классы в своих модулях и создавать экземпляры этих классов. Когда вы создаете экземпляр, вы создаете объект, основанный на выбранном классе. Класс – это форма для печенья, а объект – это само печенье. Вы можете создать несколько экземпляров одного класса. Экземпляры будут объектами, и живут они независимо друг от друга, в то время как класс – единственный в своем роде. В этом и состоит отличие между объектами и классами.

Давайте, исследуем один класс, допустим TSringList.

  1. Запустите Delphi.
  2. Поместите на форму кнопку Button, произведите два щелчка левой кнопкой мыши по компоненту Button1 и запишите программный код:
procedure TForm1.Button1Click(Sender: TObject); var Strings:TStringList; begin Strings:=TStringList.Create; Strings.Add('Это'); Strings.Add('моя'); Strings.Add('запись.'); ShowMessage('Список имеет ' + IntToStr(Strings.Count) + 'записи'); Strings.Free; Strings:=TStringList.Create; Strings.Add('Одна запись'); ShowMessage('Наш следующий список имеет ' + IntToStr(Strings.Count) + ' запись'); Strings.Free; end; end.

В первой строке, заключенной между ключевыми словами begin и end, вы вызываете функцию Сгеа tе, являющуюся конструктором. Это функция класса, поставляемая с классом, а не с экземпляром класса. Имя TStringList является именем класса, а не экземпляра. Конструктор, в свою очередь, создает экземпляр класса.

В следующих трех строках производится вызов процедуры Add экземпляра класса, которая добавляет строки в список текста . Имя Strings является именем экземпляра. Класс Т SringList может делать несколько больше, чем просто добавлять строки.

В следующей строке используется поле Со unt экземпляра, в результате чего мы узнаем число элементов в списке.

В обработчике события имеется функция Fгее, которая уничтожает экземпляр.

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

Таким образом, мы создали два экземпляра Т SringList с использованием одной переменной. В первой половине программы мы использовали переменную Strings, создали экземпляр, использовали его и уничтожили. Но сама переменная не уничтожилась, и затем мы использовали ее, снова — создали другой экземпляр, ссылаясь на него при помощи той же переменной.

Что же это означает? Это значит, что экземпляр и переменная как-то различаются.

Все дело в следующем: когда вы создаете экземпляр с помощью вызова конструктора Сгеа tе, то он помещается где-то в памяти и, следовательно, имеет адрес. Конструктор — это функция, которая после создания экземпляра возвращает адрес только что созданного экземпляра. Таким образом, в строке Strings:=TStringList.Create; функция Сгеа класса TStringList ; возвращает адрес и помещает его в переменную Strings .

Переменная Strings является указателем.

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

Фактически так происходит со всеми объектами в Object Pascal . Когда вы объявляете переменную с типом некоторого класса, вы на самом деле определяете указатель.

Заметьте, что вы не использовали символы @ или ^, как обычно делается в Object Pascal , они вам просто пока не нужны. Borland разработала следующее правило: переменная для экземпляра класса — это всегда указатель. Вам нет необходимости использовать значок ^ при объявлении переменной, и вам не надо использовать @ или ^ в вашем коде. Вы просто используете переменную так, как будто она и есть экземпляр. Но когда вы так делаете, вы не должны забывать, как все на самом деле происходит.

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

Большинство компонентов визуальной библиотеки имеют поле о wnеr (владелец). Владельцем компонента всегда является окно, в котором он находится. Если вы забываете уничтожить экземпляр одного из таких компонентов, даже если вы создали его вручную, то экземпляр автоматически уничтожится, когда владелец — окно — будет уничтожен. Кроме поля owner, у некоторых компонентов имеется поле parent (родитель) (не путайте с предком в смысле класса-предка), в этом поле хранится указатель на оконный объект, в котором он расположен.

Например, если кнопка находится на компоненте Panel окна программы, то поле owner установлено у обоих компонентов программы, а поле parent — у кнопки на Panel, а у панели — на окно программы.

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

Если вы хотите разобраться с ООП, то этот материал вам придется читать не один раз.

Компонент ListBox.

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

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

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

Компонент ListBox имеет свойство Items . Оно является просто списком элементов типа строки. Свойству Items присваивается конкретный потомок типа TStrings, например TStringList, которым вы можете непосредственно манипулировать, добавляя или удаляя строки из списка. Например, чтобы добавить строку к окну списка ListBox1 во время выполнения, вы можете просто использовать метод Items.Add. По аналогии, чтобы вставить новую строку в указанной позиции списка окна, вы можете использовать метод Insert.

Следует знать, что элементы списка нумеруются с нуля. Первый элемент – это элемент под номером 0, второй элемент – это элемент под номером 1 и т.д.

Рассмотрим пример с использованием компонента ListBox.

    1. Запустите Delphi.
    2. Запомните файл модуля под именем ListB_pas, а файл проекта под именем ListB dpr.
    3. Поместите компонент ListBox1 со страницы Standard палитры компонентов. Поместите три компонента Button на форму. Определите для первой кнопки заголовок " Очистить ", для второй — " Ввод значений ", для третьей — " Датчик чисел ". Для этого используйте свойство Caption страницы Properties инспектора объекта. Произведите щелчок по кнопкам и запишите методы обработки события OnClick для каждой кнопки:
    4. procedure TForm1.Button1Click(Sender: TObject); begin ListBox1.Items.Clear; end; procedure TForm1.Button2Click(Sender: TObject); var I:Integer; begin for I:=1 to 10 do ListBox1.Items.Add('Координата Х'+ IntToStr(I)); end; procedure TForm1.Button3Click(Sender: TObject); var J:Integer; begin Randomize; J:=0; while J < 10 do begin J:=J + Random(10); ListBox1.Items.Add('Координата Y' + IntToStr(J)); end; end; end.
    5. Щелчок левой кнопкой мыши по компоненту Button с заголовком "Очистить" удаляет содержимое компонента ListBox1. Щелчок по кнопке "Ввод значений" позволяет ввести десять последовательных чисел координаты Х в список. Щелчок по кнопке с заголовком "Датчик чисел" позволяет ввести значения координаты Y. Здесь присутствует цикл while , который использует счетчик, определяющий значения параметров случайным образом. Для этого вызывается процедура Randomize, которая инициирует генератор случайных чисел и функцию Random со значением диапазона равным 10.
    6. Вы можете вводить текстовые строки в компонент на этапе разработки приложения, используя Редактор списка строк. Дважды произведите щелчок по кнопке с тремя точками справа от слова (TStrings), используя страницу Properties инспектора объекта. Откроется диалоговое окно Редактора списка строк для свойств типа TStrings и любых его потомков. Редактор позволяет вам ввести текст в свободной форме, сформатированный в строчки во время разработки, обеспечивая, таким образом, начальное содержимое списка строк. После ввода строк необходимо нажать OK. Строки, которые вы ввели, заполняют окно списка во время разработки и при выполнении приложения. Теперь вы можете запустить свое приложение, чтобы проверить функционирование окна списка с единственным выбором.

По умолчанию, компонент ListBox становится окном списка с единственным выбором. Только один элемент в таком списке может быть выбран в каждый момент времени. Этот выбранный элемент подсвечивается. Вы можете перемещать подсветку посредством клавиш: стрелка вверх и стрелка вниз.

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

Щелчок по кнопке Button5 с заголовком "Добавить строку" даст вам возможность добавить строку в компонент ListBox1, которую вы введете в компонент Edit2.

Поместите на форму компонент Button6 с заголовком " Изменить местоположение строки". Щелчок по этой кнопке позволит вводить номер строк в компонент Edit1 и Edit2, вы сможете менять местами строки внутри компонента ListBox1.

Поместите на форму компонент Button7 с заголовком "Подсчет строк в компоненте". Щелчок по данной кнопке приводит к появлению информации в компоненте Label3 о числе записей в компоненте ListBox1.

Сортировку записей в компоненте ListBox1 по алфавиту вы можете осуществить щелчком по кнопке Button8 с заголовком "Сортировка записей по алфавиту".

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

Программный код для данного примера имеет вид:

procedure TForm1.Button4Click(Sender: TObject); var K:Integer; begin K:=StrToInt(Edit1.Text); ListBox1.Items.Delete(K); end; procedure TForm1.Button5Click(Sender: TObject); begin ListBox1.Items.Add(Edit2.Text); end; procedure TForm1.Button6Click(Sender: TObject); var I,J:Integer; begin I:=Strtoint(Edit1.Text); J:=StrToInt(Edit2.Text); ListBox1.Items.Exchange(I,J); end; procedure TForm1.Button7Click(Sender: TObject); begin Label3.Caption:='Всего '+ IntToStr(ListBox1.Items.Count) + ' записей'; end; procedure TForm1.FormCreate(Sender: TObject); var I:Integer; begin ListBox2.Items.Add('Blue'); ListBox2.Items.Add('Yellow'); ListBox2.Items.Add('Red'); end; procedure TForm1.Button8Click(Sender: TObject); begin ListBox1.Sorted:=True; end; procedure TForm1.Button9Click(Sender: TObject); begin if ListBox2.Selected[0] then ListBox2.Color:=clBlue; if ListBox2.Selected[1] then ListBox2.Color:=clYellow; if ListBox2.Selected[2] then ListBox2.Color:=clRed; end; end.

Результат работы приложения List показан на рисунке 5.

Л

итература:

    1. Марко Канту. Delphi 2 для Windows 95/NT. Москва. ООО "Малип". 1997 г.
    2. Джон Матчо. Дэвид Р. Фолкнер. Delphi. Москва. БИНОМ. 1995 г.
    3. Эндрю Возневич. Delphi. Освой самостоятельно. Москва. Восточная книжная компания. 1996 г.
    4. В.В.Фаронов. Delphi 5. Учебный курс. Москва. Издательство Нолидж. 2000 г.
    5. А. Я. Архангельский. Программирование в Delphi 5. Москва. ЗАО "Издательство Бином". 2000 г.

Владимир Скуратов

(c) компьютерная газета





© компьютерная газета