Методические указания для проведения практических и лабораторных занятий по дисциплине "Программирование на языке высокого уровня" для студентов специальностей 220200 Автоматизированные системы обработки информации и управления

Вид материалаМетодические указания

Содержание


Класс TStrings
Класс TStringList
Подобный материал:
1   2   3   4   5   6   7   8   9   10   11

Класс TStrings


Многофункциональный класс, предназначенный для хранения текстовых строк и связанных с ними объектов (любых потомков TObject). TStrings — абстракт­ный класс; он только описывает методы работы с наборами строк и сопут­ствующих им объектов, но как именно они хранятся, на его уровне не опре­делено. Его потомки очень многочисленны; они играют основную роль в компонентах-списках (TListBox, TComboBox), редакторе (TMemo) и других. Так что вам чаще всего придется иметь дело с TStrings как со свойством одного из компонентов. В дальнейшем экземпляры этого класса и порожденных от него классов мы-будем называть наборами строк. Для создания собственных наборов строк вне компонентов предназначен потомок TStrings — TStringList, который будет рассмотрен ниже.

К строкам и объектам соответственно можно получить доступ через свойства:

property Strings[Index: Integer]: string;

property Objects[Index: Integer]: TObject;

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

(Ro'l property Count: Integer;

Класс TStrings также предназначен для хранения пар вида 'параметр=значение', например, в файлах инициализации (.INI). Эту возможность реализует следу­ющее свойство:

property Values[const Name: string]: string;

При обращении к этому свойству для чтения ищется строка, содержащая подстроку (параметр) Name и символ '='. Если она найдена, возвращается то, что находится в этой строке после '='. Если нет, Values[Name] равно пустой строке. При записи: если строка, содержащая параметр Name, найдена — ее значение после '=' заменяется новым значением, если нет — строка добавля­ется. Если существующему параметру присваивается пустая строка (Valu-es[Name] := ";), то он удаляется из набора строк.

Методы класса приведены в таблице:

procedure BeginUpdate; procedure EndUpdate;

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

procedure Clear;

Осуществляет полную очистку набора.

procedure Insert(Index: Integer; const S: string);

Вставляет строку S под индексом Index.

procedure Delete(Index: Integer);

Удаляет строку с индексом Index.

function IndexOf(const S: string): Integer;

Возвращает индекс (номер в наборе) строки S. Если она не найдена, функция возвращает -1.

function IndexOfObject(AObject: TObject): Integer;

Возвращает индекс объекта в наборе. В случае неудачи возвращает -1.

function Equals(Strings: TStrings): Boolean;

Сравнивает строки вызвавшего его объекта со строками объекта Strings и возвращает True в случае равенства (сравниваются число строк и все строки попарно).

function Add(const S: string): Integer-

Добавляет строку S в конец набора и в случае успеха возвращает присвоенный ей индекс (он должен быть равен значению Count до добавления строки).

function AddObject(const S: string; AObject: TObject): Integer;

Добавляет строку в паре с объектом. Возвращает то же, что и метод Add.

procedure Exchange(Indexl, Index2: Integer);

Меняет местами пары строка+объект с индексами Indexl и Index2.

procedure Move(Curlndex, Newlndex: Integer);

Перемещает пару строка+объект с позиции Curlndex в позицию Newlndex.

procedure InsertObject(Index: Integer; const S: string; AObject: TObject);

Вставляет объект AObject и соответствую­щую ему строку S в набор под индексом Index.


Шесть методов предназначены для экспорта/импорта наборов строк:

а) в поток:

procedure LoadFromStream(Stream: TStream);

procedure SaveToStream(Stream: TStream);

б) в файл (создавая поток и вызывая два предыдущих метода):

procedure LoadFrornFile (const FileName: strings-procedure SaveToFile(const FileName: string);

в) в данные в формате текстового редактора (подряд расположенные строки, оканчивающиеся парой символов CR/LF (16-ричные коды SOD/SOA)).

procedure AddScrings(Strings: TStrings! ;

Добавляет в конец набора другой набор Strings.

procedure Assign!Source: T'Persisier-t l ;

Уничтожает прежнее содержимое набора и подставляет вместо него Source, если источник имеет тип TStrings. В противном случае возникает исключительная ситуа­ция EConvertError.


При этом метод function GetText: PChar; выгружает строки в единый массив, где они разделены парами символов CR/LF; в конце такого массива ставится нулевой байт. Размер массива не может превышать 65520 байт; поэтому строки выгружаются до тех пор, пока их суммарная длина не превосходит этого значения.

Метод procedure SetText(Text: PChar); читает строки из массива Text. Строки в массиве должны быть отделены друг от друга парой символов CR/LF; допускается и один символ LF (16-ричный код $ОА). Символы с кодами 0, $lA(+) воспринимаются как конец текста. При этом прежнее содержимое набора уничтожается.


Класс TStringList


Этот класс объединяет в себе свойства TStrings и TList простейшим способом — указатель на объект и соответствующая строка объединяются в запись, ука­затель на которую хранится в списке. В классе переопределены многие вирту­альные методы TStrings: Add, Clear, Delete, Exchange, IndexOf, Insert; он явля­ется полностью функциональным и вы можете создавать экземпляры TStringList в своей программе для работы с наборами строк и объектов (помимо тех, которые уже есть в компонентах).

Кроме унаследованных от TStrings, определены дополнительно полезные ме­тоды и свойства:

function Find(const S: string; var Index: Integer): Boolean;

Метод ищет в наборе строку S и в случае успеха возвращает результат True, а в параметре Index — ее индекс.

property Sorted: Boolean;

Свойство — признак отсортированности элементов (сортировка осуществляется через посимвольное сравнение строк). Установка Sort := True вызывает процедуру сортировки, которую можно вызвать и явно при помощи метода:

procedure Sort;

Попытка добавить или вставить элемент в отсортированный список вызывает исклю­чительную ситуацию EListError; в этом случае до выполнения действия свойству Sorted нужно присвоить значение False.

property Duplicates: TDuplicates; TDuplicates = (duplgnore, dupAccept, dupError);

Свойство определяет, что происходит при попытке добавить в список дубликат уже имеющейся строки: duplgnore — добав­ление игнорируется (отклоняется); dupError — добавление приводит к созда­нию исключительной ситуации EListError; dupAccept — одинаковые строки разре­шены. В этом случае при поиске в неотсор­тированном списке не определено, которая из строк будет найдена первой.




property OnChange: TNotifyEvent; property OnChanging: TNotifyEvent;

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



2.2. Элементы управления

Потомком TComponent является класс TControl — элемент управления Win­dows. Все то, что видит (или может увидеть) пользователь в клиентской области вашей формы во время выполнения, порождено от класса TControl (клиентская область — вся рабочая поверхность окна Windows, исключая заголовок, полосу меню и обрамление). Таким образом, потомки TControl являются визуалъньши компонентами. Далее будем называть их, как принято в Windows, элементами управления, или, где это уместно, просто элементами.

Отметим также подвох, связанный с названием "Библиотека визуальных ком­понентов" (Visual Components Library, VCL). Называя так свою библиотеку, разработчики из фирмы Borland были абсолютно правы, так как речь идет в первую очередь о новой — визуальной — технологии программирования. Но нужно помнить, что в VCL входит множество полноправных невизуальных компонентов. Например, меню — оно, конечно, видимо на экране, но не в клиентской области; поэтому формально меню не является визуальным ком­понентом.

Большинство из свойств, которые вы будете видеть и изменять в визуальных компонентах, помещенных в Инспектор объектов, впервые описаны в классе TControl. Этот класс уже обладает "поведением" — в нем предусматривается реакция на основные события.

Объект класса TControl не является окном Windows и в силу этого не может получить фокус ввода. Однако у него обязательно имеется родительский эле­мент (см. главу 2, раздел "Наследование. Методы"), обладающий этим свой­ством и отвечающий за показ дочернего элемента и обработку некоторых поступающих ему сообщений. (Раз TControl не является окном, то он не имеет контекста устройства для рисования. Этот контекст обеспечивает ему родитель. Тип родительского элемента — TWinControl — будет рассмотрен ниже).

Обратите внимание на терминологию: Owner — это владелец компонента, а Parent — его родитель, определяемый свойством property Parent: TWinControl;

Элемент управления может обрабатывать сообщения Windows. Чтобы послать собственной функции обработки элемента сообщение Windows вида Msg с параметрами WParam и LParam, можно воспользоваться методом:

function Perform(Msg, WParam: Word; LParam: Longint): Longint;

С каждым элементом управления связан некий текст, который может играть роль заголовка или редактироваться. В зависимости от роли текст может содержаться в свойствах Caption:

(РЬ) property Caption: TCaption;

TCaption = string[255];

либо Text:

property Text: TCaption;

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

function GetTextBuf(Buffer: PChar; BufSize: Integer): Integer;

procedure SetTextBuftBuffer: PChar);

function GetTextLen: Integer;

Все три метода работают, посылая в собственную функцию-обработчик со­общений объекта (через вызов метода Perform) сообщения Windows вида WM_GETTEXT, WM_SETTEXT и WM_GETTEXTLENGTH.

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

property Cursor: TCursor;

TCursor = -32768..32767;

В Delphi предопределены стандартные типы курсоров. Их имена: crDefault, crNone, crArrow, crCross, crIBeam, crSize, crSizeNESW, crSizeNS, crSizeNWSE, crSizeWE, crUpArrow, crHourGlass, crDrag, crNoDrop, crHSplit, crVSplit, crMultiDrag, crSQLWait.

Этим именам соответствуют константы со значениями от 0 до -17; под этими идентификаторами все курсоры доступны в свойстве Cursors глобального объекта Screen. Можно добавить к ним собственные курсоры, загрузив их из ресурсов и присвоив положительные идентификаторы:

{$R cursors.RES} const Curl = 1; Cur2 = 2;

procedure TFormI. For-mCreate (Sender: TObject);

begin

Screen.Cursors[Curl] := LoadCursor(hinstance, 'CUR_1');

Screen.Cursors[Cur2] := LoadCursor(hinstance, 'CUR_2<);

end;

Познакомиться с имеющимися видами курсоров можно, скомпилировав прила­гаемый на дискете пример CURSORS.

У каждого элемента есть два свойства, отражающие его стиль и состояние. Они могут сослужить программисту хорошую службу.

Первый из них — набор флагов, управляющих поведением компонента:

property ControlStyle: TControlStyle;

TControlStyle = set of (csAcceptsControls, csCaptureMouse, csDesignInteractive, csClickEvents, csFramed, csSetCaption, csOpaque, csDoubleClicks, csFixedWidth, csFixedHeight);

Эти флаги означают, что данный компонент имеет следующие особенности:

с sAccept sControls

Может содержать другие (дочерние) элементы управления. Таким свойством обладают не все элементы: обладающие им называются группирующими и рассмотрены в отдельном

разделе.

csCaptureMouse

Может получать сообщения от мыши.

csDesignInteractive

Транслирует нажатия правой кнопки мыши в нажатия левой во время разработки.

csFramed

Имеет обрамление (черным прямоугольником единичной толщины).

csSetCaption

Позволяет при изменении имени менять синхронно и свойство Text (если Text не был явно переустановлен).

csOpaque

Фон элемента непрозрачен. Это означает, что при пересечении нескольких компонентов на экране располо„.:мный под ним виден не будет.

csClickEvents

Воспринимает щелчки мышью.

с sDoubleC1i cks

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

csFixedWidth, csFixedHeight

Имеет фиксированную ширину или высоту соответственно. Она не изменяется при масштабировании компонента.


Набор флагов, отражающих состояние элемента, описывается свойством:

property ControlState: TControlState;

TControlState = set of (csLButtonDown, csClicked, csPalette, csReadingState, csAlignmentNeeded, csFocusing, csCreating);

Они означают следующее:

csLButtonDown

Над элементом в данный момент нажата левая кнопка мыши.

csClicked

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

csPalette

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

csReadingState

Элемент в данный момент читается из потока.




сsAlignmentNeeded

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

csFocusing

В данный момент происходит получение элементом фокуса ввода.

csCreating

Элемент создается (этот флаг в настоящий момент не задействован).


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

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

property PopupMenu: TPopupMenu;

Подробно о его создании и использовании рассказано в разделе, посвященном меню.


2.3. Положение, размеры и выравнивание элементов управления

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

property BoundsRect: TRect;

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

procedure SetBounds(ALeft, АТор, AWidth, AHeight: Integer);

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

(pb) property Left: Integer;

J property Top: Integer;

property Width: Integer;

(Pb) property Height: Integer;

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

(Ro) property ClientRect: TRect;

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

property ClientHeight: Integer;

property ClientWidth: Integer;

Свойство ClientOrigin задает положение начала клиентской области относитель­но экрана:

(Ro) property ClientOrigin: TPoint;

Если же нужно связать с координатной системой экрана произвольную точку, пользуйтесь парой методов (не путать с одноименными функциями Windows API):

function ClientToScreen(const Point: TPoint): TPoint;

function ScreenToClient(const Point: TPoint): TPoint;

Очень важную часть работы по управлению размерами и расположением эле­ментов выполняет свойство:

(Pb) property Align: TAlign;

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

TAlign = (aiNone, alTop, alBottom, alLeft, alRight, alClient);

aINone — выравнивание отсутствует;

alTop, alBottom, alLeft, alRight — выравнивание происходит по соответст­вующей стороне родителя;

alClient — компонент занимает все пространство клиентской области родителя.

Выравнивание гарантирует, что при изменении размеров родителя относитель­ная позиция дочернего элемента не меняется. Это свойство имеет приоритет над простым изменением положения и размеров. Если новые координаты эле­мента противоречат способу его выравнивания (например, перемещение вверх при alBottom), изменения отвергаются и элемент возвращается к первоначаль­ным координатам. Свойство Align незаменимо при организации панелей инструментов и строк состояния — они могут перемещаться и видоизменяться вместе с содержащей их формой. Для временного отключения действия свойства Align предназначены методы:

procedure DisableAlign;

procedure EnableAlign;

Эти методы управляют возможностью выравнивания потомков данного эле-мекга, они должны вызьшаться в паре. Для восстановления выравнивания элементов в соответствии с Align есть метод:

procedure Realign;

В следующем примере использование методов DisableAlign и EnableAlign поз­воляет настроить выравнивание панели по тому краю формы, на который пользователь перетащит ее мышью:

procedure TFormI.FormCreate(Sender: TObject);

begin

Panell.Align := alBottom;

Moving := False;

end;

procedure TFormI.PanellMouseDown(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

if not Moving then

begin

Formi.DisableAlign;

Moving := True;

end;

end;

procedure TFonnl.PanellMouseMove(Sender: TObject;Shift: TShiftState; X, Y: Integers);

begin

if Moving then with Panell do

begin

Left := Left + X - Width div 2;

Top := Top + Y - Height div 2;

Panell.Caption := Format('%d,%d',[Left,Top]);

end;

end;

procedure TFormI.PanellMouseUp(Sender: TObject;Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

var LastPos : TPoint; rO, rl, r2 : real;

begin

if Moving then

begin

Moving := False;

Panell.Caption := '';

LastPos := Point(Panell.Left + X, Panell.Top + Y) ;

if LastPos.X<=0 then LastPos.X := 1;

if LastPos.X>=ClientWidth then LastPos.X := ClientWidth-1;

if LastPos.Y<=0 then LastPos.Y := 1;

if LastPos.Y>=ClientHeight then LastPos.Y := ClientHeight-1;

rO := ClientWidth/ClientHeight;

rl := LastPos.X/LastPos.Y;

r2 := LastPos.X/(ClientHeight - LastPos.Y);

with Panell do if rl < rO then if r2 < rO

then Align := alLeft else

Align := alBottom else if r2 < rO

then Align := alTop else Align := alRight;

Formi.EnableAlign;

end;

end;


2.4. Активность и видимость элементов управления

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

(Pb) property Enabled: Boolean;

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

Свойство, определяющее возможность видимости элемента во время испол­нения:

(Pb) property Visible: Boolean;

Во время разработки все компоненты являются видимыми. Изменять это свой­ство непосредственно во время выполнения можно, используя два следующих метода:

procedure Show;

procedure Hide;

Напомним, что, так как Visible является свойством, то выражение visible: =True не является простым присваиванием. Оно неявно содержит все необходимые операции для показа элемента управления. Это же касается всех остальных свойств компонентов, реакция на изменение которых должна произойти не­медленно.

Почему выше была применена формулировка "возможность видимости", а не "видимость"? Чтобы элемент был виден на экране, одного значения свойства Visible недостаточно. Нужно, чтобы видимыми были все предки элемента в иерархии. Реально видимость элемента можно узнать, пользуясь свойством:

(Ro) property Showing: Boolean;

Это свойство устанавливается при изменении свойства Visible. Оно доступно только для чтения. Нужно иметь в вицу, что при изменении видимости родительского элемента Showing не изменяется и может в какой-то момент не соответствовать истинному состоянию. Обновляет состояние свойства Showing для компонента метод:

procedure UpdateControlState;

Отрисовкой (изменением изображения на экране) элемента управления "заве­дуют" следующие методы:

procedure Invalidate;

Отрисовывает компонент, вызывая функцию API InvalidateRect.

procedure update;

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

Этот метод объединяет два предыдущих. Если элемент управления непрозрачный (имеет флаг csOpaque), занимаемый им прямоугольник предварительно очищается.

procedure Repaint;

procedure Refresh;

Представляет собой вызов Repaint. Рекомендуется для вызова отрисовки.


2.5. Оконные элементы управления

Понятие окна Windows инкапсулировано в потомке TControl — классе TWinControl. Такой компонент получает соответствующий атрибут _ дескриптор окна, определяемый свойством:

(Ro) property Handle: HWnd;

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

Возможны ситуации, когда компонент уже создан, но еще не имеет дескриптора как окно. Два метода управляют созданием дескриптора:

function HandleAllocated:Boolean;

procedure HandleNeeded;

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

Важным свойством TWinControl является то, что он может содержать другие — дочерние — элементы управления. Они упорядочены в виде списка. Если быть точным, то списков на самом деле два — для неоконных и оконных дочерних элементов. Но "видны" они как один объединенный — сначала первый, потом второй. Методы и свойства для работы с этим списком приведены в таблице:

(Ro) property Controls[Index: Integer]: TControl;

Содержит список дочерних элементов.

(Ro) property ControlCount: Integer;

Содержит число элементов в списке.

function ContainsControl(Control: TControl): Boolean;

Проверяет наличие элемента в списке.

function ControlAtPos(const Pos: TPoint; AllowDisabled: Boolean): TControl ;

Отыскивает в списке элемент, которому принадлежит заданная точка (в системе координат собственной клиентской облас­ти). Флаг AllowDisabled показывает, раз­решен ли поиск среди пассивных (свойство Enabled которых равно False) элементов.

procedure InsertControl(AControl: TControl) ;

Вставляет элемент в конец списка.

procedure RemoveControl(AControl: TControl);

Удаляет элемент из списка.

procedure Broadcast(var Message);

Рассылает всем дочерним элементам из списка сообщение Message.


С каждым оконным компонентом можно связать контекстную помощь. Кон­текст помощи — это индекс, указывающий на определенную информацию в файле справочной системы, связанном с приложением:

property HelpContext: THelpContext;

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

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

Прокрутку (скроллинг) элементов на интервал DeltaX, DeltaY осуществляет метод:

procedure ScrollBy(DeltaX, DeltaY: Integer);

Прибегая к вызову этой процедуры, можно при желании осуществить про­крутку нестандартным способом, т. е. без привлечения полос прокрутки. При­веденный ниже фрагмент кода — составная часть примера IMGSCROL на дискете— позволяет "тащить" изображение Imagel вслед за мышью с нажатой кнопкой:

type TMouseState = (msNormal, msDragging);

var OldPos, NewPos, MaxShift: TPoint; PMouseState : TMouseState;

procedure TFormI.ScrollMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integers);

begin

MaxShift.X := Imagel.Parent.Width - Imagel.Width;

MaxShift.Y := Imagel.Parent.Height - Imagel.Height;

if (MaxShift.X > 0) and (MaxShift.Y > 0) then Exit;

FMouseState := msDragging;

OldPos := Point(X, Y) ;

Screen.Cursor := crDrag;

end;

procedure TFormI.ScrollMouseMove(Sender : TObject; Shift: TShiftState; X, Y: Integers);

begin

if FMouseState = msDragging then

begin

NewPos := Point(X - OldPos.X, Y - OldPos.Y) ;

if Imagel.Left + NewPos.X > 0 then NewPos.X := - Imagel.Left;

if Imagel.Left + NewPos.X < MaxShift.X

then NewPos.X := MaxShift.X - Imagel.Left;

if Imagel.Top + NewPos.Y > 0 then NewPos.Y := - Imagel.Top;

if Imagel.Top + NewPos.Y < MaxShift.Y

then NewPos.Y := MaxShift.Y - Imagel.Top;

Imagel.Parent.ScrollBy(NewPos.X, NewPos. Y) ;

end;

end;

procedure TFormI.ScrollMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

FMouseState -.= msNormal;

Screen.Cursor := crDefault;

end;

Обратите внимание, что прокрутка неоконного компонента Imagel осуществ­ляется посредством вызова Image l.Parent.ScrollBy. Это свидетельствует о том, что конкретный родительский тип для этого безразличен. В примере изобра­жение помещено на панель (TPanel). Впрочем, метод ScrollBy используется также и полосами прокрутки, которые есть в компоненте TScrollingWinControl и его потомках, например, в TForm.

В VCL предусмотрена возможность написания приложений, которые будут сохранять относительный размер и положение при всех разрешениях дисплея. Более подробно эти механизмы описаны в разделе, посвященном формам; для TWinControl упомянем лишь метод

procedure ScaleBy(M, D: Integer);

который изменяет масштаб элемента управления в M/D раз, при этом верхний левый угол остается неподвижным. Так же изменяются и размеры всех дочерних элементов. Соответственно изменяется и масштаб шрифта (свойство Font). Флаги csFixedWidth и csFixedHeight в свойстве ControlStyle предотвращают изменение ширины или высоты.

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

(Рb) property Ctl3D: Boolean;

Нужно уточнить, что это свойство есть не у всех компонентов. Для части компонентов трехмерность реализована средствами VCL; другая же часть (радиокнопки, флажки и др.) требует для создания трехмерного эффекта до­ступа к библиотеке CTL3DV2.DLL.

Шрифт, которым выводится текст, связанный с элементом управления:

property Font: TFont;

Кисть, используемая для закрашивания рабочей области оконного элемента управления, представлена свойством:

(Ro) property Brush: TBrush;

Она имеет цвет, содержащийся в свойстве Color (по умолчанию clWindow). На уровне TControl оно доступно только по чтению:

property Color: TColor;


2.6. Реакция на события от мыши и клавиатуры

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

(р) property OnMouseDown: TMouseEvent;

(Pb) property OnMouseUp: TMouseEvent;

TMouseEvent = procedure(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer) of object;

Параметры:

Sender — элемент-источник сообщения (обычно равен Self);

Button — идентификатор одной из кнопок;

TMouseButton = (mbLeft, mbRight, mbMiddle);

Shift — множество, которое может содержать элементы:

ssAlt, ssCtrl, ssShift — в зависимости от состояния этих клавиш;

ssLeft, ssRight, ssMiddle, ssDouble — в зависимости от нажатия кнопок мыши (ssDouble — нажать! и правая, и левая кнопки);

X, Y — координаты нажатия (в системе координат клиентской области получателя).

При перемещении мыши возникает событие:

(Pb) property OnMouseMove: TMouseMoveEvent ;

TMouseMoveEvent = procedure(Sender: TObject; Shift: TShiftState; X, Y: Integer) of object;

Использование сообщений от мьшш уже встречалось в примерах, приведенных вьппе (например, см. разд. "Положение, размеры и выравнивание элементов управления").

Два события извещают о щелчке и двойном щелчке левой кнопкой мыши над компонентом:

(pt) property OnClick: TNotifyEvent;

(Pb) property OnDblClick: TNotifyEvent;

Отменить генерацию этих событий можно, удалив флаг csClickEvents из слова состояния элемента (ControlStyle). Для некоторых компонентов (например, кно­пок) OnClick возникает еще и при нажатии определенных клавиш на клавиатуре, а также вследствие вызова метода Click.

События, связанные с мышью, могут быть получены потомками TControl. В отличие от них, реакцию на события от клавиатуры могут иметь только оконные элементы управления ("могут", т. к. на уровне TControl и TWinControl эти события только описаны, но не опубликованы). Таким образом, есть компоненты (в том числе в Палитре компонентов), не имеющие связи с этими событиями из-за ее ненадобности. Впрочем, их меньшинство, и материал в этом разделе обобщен вполне обоснованно.

Нажатие и отпускание клавиш клавиатуры могут инициировать следующие события:

property OnKeyDown: TKeyEvent;

property OnKeyUp: TKeyEvent;

eyEvent = procedure(Sender: TObject; var Key: Word;

Shift: TShiftState) of object;

Генерация этих событий встроена в обработчики сообщений Windows WMJCEYDOWN, WMJSYSKEYDOWN и WM_KEYUP, WM_SYSKEYUP соответст­венно. Обработчику передаются:

Sender — источник сообщения;

Shift — состояние специальных клавиш и кнопок мыши во время нажатия (отпускания);

Key — код нажатой клавиши, представляющий собой виртуальный код клавиши Windows (константы вида VK_XX, например, VK_F1, VK_ESCAPE и т. п.). Обратите внимание, что Key является var-параметром; т. е. его значение может быть изменено программистом.

Другое событие, возникающее вследствие нажатия клавиши:

property OnKeyPress :. TKeyPressEvent;

TKeyPressEvent = procedure(Sender: TObject; var Key: Char) of object;

Это событие возникает при вводе с клавиатуры символа ASCII, т. е. оно не ге­нерируется, например, при нажатии функциональных клавиш или . Обработчик события вызывается при нажатии буквенных (в т. ч. вместе с ), цифровых клавиш, комбинаций + .. + (коды ASCII #1..#26), , , , + (код #3) и некоторых других. Также код ASCII можно сгенерировать, нажав <А11>+<десятичньш код символа> на числовой клавиатуре (Numeric Pad).

Событие OnKeyPress соответствует сообщению Windows WM_CHAR.

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

(Pb) property KeyPreview: boolean;

установлено в True, то сначала все три вида сообщений поступают к ее обработчикам, и только потом — к элементу управления. Если при этом в них обнулить параметр Key, то в элемент сообщение не поступит вообще. В приведенном ниже примере клавиша резервируется для изменения со­стояния формы:

procedure TFormI.FormCreate(Sender: TObject);

begin

KeyPreview := True;

end;

procedure TFonnl.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

begin

if Key = VK_F5 then

begin

if ssCtrl in Shift then WindowState := wsNormal

else if Shift = [] then

WindowState := wsMaximized;

Key : = 0 ;

end;

end;


2.8. Фокус ввода

Будучи окнами Windows, TWinControl и его потомки должны управлять фоку­сом ввода (состоянием, когда они получают и обрабатывают входные сооб­щения). Они имеют предназначенные для этого методы:

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



function Focused: Boolean-

Показывает, имеет ли элемент в данный момент фокус ввода.

function CanFocus: Boolean;

Возвращает True, если оконный элемент может по­лучить фокус ввода (для этого он и все его роди­тельские оконные элементы управления должны быть активными (Enabled) и видимыми).

procedure SetFocus;

Запрашивает у родительской формы получение фокуса ввода.


При получении и утере фокуса оконными компонентами происходят события:

(Pb) property OnEnter: TNotifyEvent;

(Р1э) property OnExit: TNotifyEvent;

TNotifyEvent — простейшее событие — извещение, не имеющее параметров. Свойство

(Pb) property TabStop: Boolean;

показывает, есть ли на данном элементе табулостоп. Между элементами формы, у которых TabStop установлено в Тше, можно передвигаться (перемещать фокус ввода) нажатиями клавиш /+. Очередность перехода фокуса определяется специальным списком. Положение элемента управления в родительском списке табулостопов определяется при помощи свойства:

(Pb) property TabOrder: TTabOrder;

TTabOrder = -1..32767;

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

Можно получить и весь список, содержащий иерархию дочерних элементов, имеющих табулостоп:

procedure GetTabOrderList(List: TList) ;

Этот метод добавляет в уже существующий список List все дочерние компо­ненты, имеющие табулостоп; каждый из них при добавлении делает то же самое. Таким образом, элементы списка имеют тип TWinControl.

Два метода предназначены для управления показом перекрывающихся до­черних элементов управления:

procedure BringToFront;

procedure SendToBack;

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

Класс инкапсулирует шрифт Windows. В Delphi допускаются только горизон­тально расположенные шрифты. В конструкторе объекта по умолчанию принимается шрифт System цвета clWindowText размера 10 пунктов.