Методические указания для проведения практических и лабораторных занятий по дисциплине "Программирование на языке высокого уровня" для студентов специальностей 220200 Автоматизированные системы обработки информации и управления
Вид материала | Методические указания |
СодержаниеКласс TStrings Класс TStringList |
- Рабочая программа по дисциплине Программирование на языке высокого уровня для специальности, 182.97kb.
- Соболева Наталья Владимировна методические указания, 73.26kb.
- Методические указания к проведению лабораторных работ. Специальность 23. 01. 02 «Автоматизированные, 1178.37kb.
- Рабочая программа По дисциплине «Системы искусственного интеллекта» для специальности, 86.74kb.
- Рабочая программа По дисциплине «Программирование на языке высокого уровня» По специальности, 280.81kb.
- Р. Е. Алексеева кафедра ису программирование на языке высокого уровня методические, 57.65kb.
- Рабочая программа по дисциплине «Алгоритмические языки и программирование» Для специальности, 208.45kb.
- Рабочая программа дисциплины «Объектно-ориентированное программирование» для специальности, 325.53kb.
- А. В. Яковлев Операционные системы и системное программирование Раздел Операционная, 1847.03kb.
- Рабочая программа дисциплины «Автоматизированные информационные системы» для специальности, 301.29kb.
Класс 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 — элемент управления Windows. Все то, что видит (или может увидеть) пользователь в клиентской области вашей формы во время выполнения, порождено от класса 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, т. е. оно не генерируется, например, при нажатии функциональных клавиш или
Событие 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 пунктов.