Справочник по компонентам Delphi. Часть 2

ОГЛАВЛЕНИЕ

Кнопки

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

Основным событием, связанным с нажатием кнопки (любым способом) явля­ется:

(Pb) property OnClick: TNotifyEvent;

Под "любым способом" здесь подразумевается щелчок мышью, нажатие комбинации клавиши — акселератора, нажатие <Enter> или <Esc> (только для некоторых кнопок) или вызов метода Click из программы.

Текст кнопки, появляющийся на ее поверхности, определен в свойстве:

(Pb) property Caption: string;

Если в составе текста есть амперсанд ('&'), то следующий за ним символ используется в акселераторе, и нажатие комбинации клавиш <АН>+<символ> вызывает нажатие кнопки.

Водораздел среди кнопок проходит по тому, что именно означает нажатие. Ряд кнопок — TRadioButton, TCheckBox и группа TRadioGroup — предназ­начен для ввода или переключения фиксированных параметров, и прог­раммиста более интересует их состояние в некоторый момент времени, чем сам факт нажатия. Кнопки TButton, TSpinButton и TBitBtn напротив, как правило, своим нажатием инициируют немедленные действия.

Кнопка TSpeedButton может успешно служить для решения обеих задач.

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

Модальная форма, или модальный диалог — специальная разновидность окон Windows (и форм Delphi), предназначенная для ввода пользователем необ­ходимых программе данных или выбора одного ответа из нескольких вариантов. Обычно при этом ему предоставляется несколько кнопок, соответ­ствующих вариантам. Вплоть до получения ответа в модальном диалоге поль­зователь не может переключиться на другие окна той же задачи, а в системном модальном диалоге — и на другие задачи. Для использования в таких случаях предназначены стандартная кнопка Windows TButton и ее младшая сестра TBitBtn, отличающаяся только наличием картинки на ее поверхности. При их нажатии значение свойства ModalResult кнопки передается одноименному свой­ству формы, где такое изменение означает вывод формы из модального сос­тояния и ее закрытие:

(Pb) property ModalResult: TModalResult;TModalResult = Low(Integer) ..High(Integer);

В модальной форме могут быть предусмотрены две специальные кнопки, со­ответствующие положительному и отрицательному решениям. Одна из них срабатывает при нажатии на клавиатуре <Enter>, другая — <Esc>. Любая кнопка может получить такой статус, установив в True соответственно одно из свойств:

(Pb) property Default: Boolean;(Pb) property Cancel: Boolean;

У двух рассмотренных кнопок результат, который при нажатии кнопки пере­дается модальной форме, будет соответственно равен mrOk и mrCancel.

Ниже рассмотрим имеющиеся в распоряжении программиста варианты кнопок. Описанные выше свойства перечисляются, но не комментируются.


 

Компонент TButton

TObject -> TPersistent -> TCornponent -> TControl -> TWinControl -> -*TButtonControl -> TButton

Модуль STDCTRLS

Страница Палитры компонентов Standard

Обычная кнопка Windows. В этом компоненте опубликованы только приве­денные выше свойства Default, Cancel, Caption, ModalResult и OnClick. Двойной щелчок на кнопке не предусмотрен.


Компонент TBitBtn

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TButtonControl -> -TButton -> TBitBtn

Модуль BUTTONS

Страница Палитры компонентов Additional

Эта кнопка, будучи потомком TButton, может нести на себе пиктограмму и имеет рад дополнительных удобств в использовании. В Delphi уже определены стандартные виды кнопок:

(Pb) property Kind: TBitBtnKind;
TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose, bkAbort, bkRetry, bklgnore, bkAll);

Для каждой из них определены: передаваемый форме результат (ModalResult):

BitBtnModalResults: array[TBitBtnKind] of TModalResult=(0, mrOk, mrCancel, 0, mrYes, mrNo, 0, mrAbort, mrRetry, mrlgnore, inrAll);

а также название и картинки для разных состояний. Достаточно установить значение свойства Kind, и кнопка сразу приобретет нужный вид. Более того, некоторые из видов кнопок при нажатии сразу совершают опре­деленные действия. Так, bkHelp осуществляет инициализацию системы помощи со своим (или ближайшим ненулевым родительским) контекстом. Кнопка вида bkClose закрывает форму, которой она принадлежит, вызывая ее метод Close.

Кнопка будет отнесена к виду bkCustom, если она:

  • назначена Default, но при этом не принадлежит множеству [bkOk, bkYes];
  • назначена Cancel, но не принадлежит множеству [bkCancel, bkNo];
  • у нее изменена пиктограмма;
  • модальный результат не соответствует определенному для этого вида кно­пок.

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

(Pi) property Style: TButtonStyle;
TButtonStyle = (bsAutoDetect, bsWin31, bsNew);

Стиль bsNew соответствует Windows 95. В любом случае корректным будет применение стиля bsAutoDetect, который сам распознает версию системы. Пиктограмма кнопки, которая вместе с текстом видна на ее поверхности, определяется свойством:

(Pb) property Glyph: TBitmap;

Для создания эффекта нажатия картинка должна немного изменяться в зависимости от состояния; кроме того, отдельная картинка нужна для неактивного состояния (когда нажатие не воспринимается). В свойстве Glyph должна быть одна битовая карта, но она может содержать картинки сразу для нескольких состояний кнопки (максимум четыре). Они интерпретируются как соответствующие нормальному (отжатому), запрещенному (неактивному), нажатому и утопленному состояниям (последнее применяется только для кно­пок TSpeedButton). Для этого картинки должны быть расположены подряд

вплотную по горизонтали. Например, при размере картинок 16х16 нужна объединенная битовая карта 64х16. Если каждая из картинок квадратная и ширина общей картинки нацело делится на высоту, то при присвоении ее свойству Glyph система сможет распознать их и скорректировать количество, определяемое свойством:

(pb) property NumGlyphs: TNumGlyphs;
TNumGlyphs = 1..4;

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

Три свойства отвечают за расположение текста и картинки на поверхности кнопки:

(Pb) property Layout: TButtonLayout;

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

TButtonLayout = (biGlyphLeft, biGlyphRight, biGlyphTop, biGlyphBottom);

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

(Pb) property Margin: Integer;

Промежуток между пиктограммой и текстом равен:

(Pb) property Spacing: Integer;

Если свойства Margin, Spacing или оба не заданы (по умолчанию равны -1), значения этих промежутков выбираются системой. Кнопка также имеет метод Click и свойства Caption, ModalResult, Default и Cancel. Статус Default получают кнопки видов bkOk, bkYes, a Cancel — кнопки видов bkCancel, bkNo.


Компонент TCheckBox

TObject -> TPersistent -> TConiponent -> TControl -> TWinControl -> TButtonControl -> TCustoniCheckBox -> TCheckBox

Модуль STDCTRLS

Страница Палитры компонентов Standard

Кнопка с независимой фиксацией, или флажок. Является стандартным элемен­том управления Windows.

Состояние кнопки отражает свойство:

(Pb) property State: TCheckBoxState;

Оно может принимать одно из трех значений:

TCheckBoxState = (cbUnchecked, cbchecked, cbGrayed) ;

Способ перехода из состояния в состояние при нажатии устанавливается свой­ством:

(Pb) property AllowGrayed: Boolean;

Если оно равно False, кнопка имеет два состояния и при каждом нажатии переходит из cbUnchecked в cbChecked и обратно. Если AllowGrayed = True, кнопка имеет три состояния и при нажатиях движется по циклу cbGrayed — cbChecked — cbUnchecked.

Показывает, отмечена mi кнопка (т. е. State = cbChecked), свойство:

(Pb) property Checked: Boolean;

Оно доступно для записи — с его помощью можно и отмечать кнопки. Зна­чение False соответствует cbUnchecked.

Выравнивание текста (только по правому или левому краю) задается при помощи свойства:

(Pb) property Alignment: TLeftRight;
TLeftRight = taLeftJustify..taRightJustify;

Кнопка также имеет свойство Caption. Двойной щелчок на кнопке не преду­смотрен. 

Компонент TRadioButton

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TButConControl -> TRadioButton

Модуль STDCTRLS

Страница Палитры компонентов Standard

Радиокнопка (переключатель), или кнопка с зависимой фиксацией — также стандартный элемент управления Windows. Особенностью радиокнопок явля­ется механизм их переключения. Они группируются автоматически, то есть при выборе одной из них все остальные, принадлежащие тому же элементу управления или форме, освобождаются. Для того чтобы в форме можно было использовать несколько независимых групп радиокнопок, используйте специальные компоненты (см. раздел "Группирование компонентов").

Свойство

(Pb) property Checked: Boolean;

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

У радиокнопки имеется свойство Caption, содержащее связанньш с ней текст. Выравнивание текста радиокнопки определяется свойством

(Pb) property Alignment: TLeftRight;

и может проводиться только по левому или по правому краю. У этого компонента предусмотрено также событие:

(Pb) property OnDblClick;

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


Компонент TSpeedButton

TObject -> TPersistent -> TComponent -> TControl -> TGraphicControl -> TSpeedButton

Модуль BUTTONS

Страница Палитры компонентов Additional

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

(pd) property Grouplndex: Integer;

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

(Pb) property AllowAlIUp: Boolean;

которое описывает поведение кнопок в группе, а именно: могут ли все кнопки одновременно быть отжаты. Если AllowAlIUp равно False (по умолчанию), на­жатую кнопку в группе можно отпустить, лишь нажав другую. Если AllowAlIUp равно True, кнопку можно отпустить повторным нажатием.

Если вы хотите фиксировать одну кнопку TSpeedButton, ей нужно присвоить уникальный групповой индекс, а AllowAlIUp установить в True. Пример использования такой кнопки есть в примере DDEINFO на прилагаемой дискете.

Поскольку в группе не могут одновременно находиться кнопки с различным значением этого свойства, при нажатии кнопки и изменении Grouplndex свой­ство AllowAlIUp "рассылается" (присваивается) остальным кнопкам с тем же значением Grouplndex. В группе не может быть нажато более одной кнопки. Определяет, нажата ли кнопка, свойство:

(Pb) property Down: Boolean;

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

Текст кнопки определяет свойство Caption. Компонент имеет те же правила и свойства рисования картинки, что и TBitBtn. Они описываются свойствами Glyph, NumGlyphs, Layout, Margin и Spacing.

Для имитации щелчка предусмотрен метод Click. Двойной щелчок для TSpeedButton возможен только на нажатой кнопке — иначе он интер­претируется как обычный. Описывается свойством:

(Pb) property OnDblClick; 


 

Компонент TRadioGroup

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomControl -> TCustomGroupBox -> TCustomRadioGroup -> TRadioGroup

Модуль EXTCTRLS

Страница Палитры компонентов Standard

Готовая группа радиокнопок, содержащая все средства для управления ими. Каждая радиокнопка в группе наследует все свойства TRadioButton. Радиокнопки могут располагаться в несколько столбцов.

Свойство

(Pb) property Columns: Integer;

устанавливает число столбцов с радиокнопками. Оно не должно превышать 16. Индекс нажатой радиокнопки в группе определяется свойством:

(Pb) property Itemlndex: Integer;

Индекс исчисляется от 0. Если он равен -1, mi одна радиокнопка в группе не нажата.

Набор строк с заголовками радиокнопок содержится в свойстве:

(Pb) property Items: TStrings;

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



Компонент TSpinButton

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TSpeenButton

Модуль SPIN

Страница Палитры компонентов Samples

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

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

(Pb) property DownGlyph: TBitmap;(Pb) property UpGlyph: TBitmap;

Кнопка не имеет события OnClick. При нажатии нижней и верхней кнопок соответственно возникают события:

property OnDownClick: TNotifyEvent;property OnUpClick: TNotifyEvent;

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

(Pb) property FocusControl: TWinControl; 


 

Ввод и редактирование текста

В Палитру компонентов входят три компонента, позволяющие вводить и редактировать текст (далее — редактирующие элементы). На базе стандартного редактирующего элемента управления Windows построены два основных ком­понента — строка ввода TEdit и многострочный редактор TMemo. На базе первого из них для ввода данных по шаблону создан третий компонент — TMaskEdit.

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

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

property Text: TCaption;
TCaption = string[255];

Часть текста может быть выделена. Свойства

property SelStart: Integer;
property SelLength: Integer;

определяют начало и длину выделенного в редакторе текста (измеряемые в количестве символов). Сам выделенный текст содержится в строке, определя­емой свойством:

property SelText: string;

Метод

procedure ClearSelection;

исключает из текста весь выделенный фрагмент, а метод

procedure SelectAll;

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

function GetSelTextBuf(Buffer: PChar; BufSize: Integer): Integer;
procedure SetSelTextBuf(Buffer: PChar);

Они могут быть полезны для получения текста типа pChar, который приме­няется в функциях API Windows.

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

procedure CopyToClipboard;procedure CutToClipboard;procedure PasteFromClipboard;

Очистить весь текст в редакторе можно при помощи метода:

procedure Clear;

Наконец, свойство

property Modified: Boolean;

устанавливает, изменялся ли текст в процессе редактирования.


Компонент TEdit

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomEdit -> TEdit

Модуль STDCTRLS

Страница Палитры компонентов Standard

Этот компонент не содержит собственного кода, в нем только опубликованы свойства его предка TCustomEdit. Он представляет собой редактируемую стро­ку (далее — просто редактор).

Стиль обрамления этого компонента

(Pb) property BorderStyle: TBorderStyle;

по умолчанию равен bsSingle. Если свойство

(Pb) property AutoSize: Boolean;

равно True, компонент изменяет свою высоту в зависимости от размера шрифта (свойство Font). Для того чтобы изменения имели место, должен еще быть установлен стиль обрамления bsSingle.

Вводимый в редактор текст может автоматически подвергаться некоторым преобразованиям.

Преобразование, задаваемое свойством CharCase, позволяет автоматически пре­образовывать все символы только в верхний или только в нижний регистр:

(Pb) property CharCase: TEditCharCase;
TEditCharCase = (ecNormal, ecUpperCase, ecLowerCase);

По умолчанию установлен стиль ecNormal и преобразования не происходит. Аналогично, свойство

(Pb) property OEMConvert: Boolean;

определяет необходимость автоматического преобразования вводимых симво­лов из кодировки OEM в ANSI и обратно. Такое свойство часто бывает нужно при обработке текста в кодировке MS-DOS.

Два следующих свойства описывают поведение выделенного текста при пере­ходе фокуса. Первое из них

(Pb) property AutoSelect: Boolean;

описывает реакцию редактирующего элемента при получении фокуса. Если оно установлено в True (по умолчанию это так), то при получении фокуса ввода весь текст в нем выделяется независимо от состояния свойства SelText. Если AutoSelect установлено в False, то при получении фокуса выделяется лишь то, что было выделено до его утери.

После утери фокуса редактором выделенный в нем текст обычно теряет цве­товое выделение. Чтобы оно оставалось, установите в False второе свойство:

(Pb) property HideSelection: Boolean;

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

(Pb) property MaxLength: Integer;

определяет максимальную длину текста редактора в символах. Если значение этого свойства равно 0, то ограничений на длину текста нет.

Свойство PasswordChar предназначено для ввода пароля с использованием редактора:

(Pb) property PasswordChar: Char;

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

Можно запретить возможность редактирования текста. Если значение свойства:

(Pb) property Readonly: Boolean;

равно True, текст изменить нельзя.

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

(Pb) property OnChange: TNotifyEvent; 

Компонент ТМеmo

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomEdit -> TCustomMemo -> TMemo

Модуль STDCTRLS

Страница Палитры компонентов Standard

Компонент представляет собой многострочный редактор текста. Содержимое редактора представлено как объект, содержащий текст в виде набора строк:

(Pb) property Lines: TStrings;

Текст в редакторе может выравниваться по левому, правому краям и по центру:

(Рb) property Alignment: TAlignment;
TAlignment = (taLeftJustify, taRightJustify, taCenter);

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

property WantReturns: Boolean;
property WantTabs: Boolean;

обращены в True, символы передаются редактору. Обратим внимание на то, что если установлено WantTabs, то с помощью клавиатуры передать фокус такому редактору можно, а после этого отдать другому компоненту — нельзя. Если свойства равны False, символы передаются форме. В этом случае для ввода этих символов в редактор можно воспользоваться комбинациями <Ctrl>+<Enter> и <Ctrl>+<Tab> соответственно.

Два свойства отвечают за организацию прокрутки текста в окне редактора:

(Pb) property Wordwrap: Boolean ;

— отвечает за поведение редактора при достижении правой границы во время набора текста. Если свойство равно True, то при этом происходит переход на новую строку. В случае False при достижении правой границы происходит горизонтальная прокрутка текста и пользователь может продолжать набор; на новую строку можно перейти, нажав <Enter>;

(Pb) property ScrollBars: TScrollStyle;
TScrollStyle = (ssNone, ssHorizontal, ssVertical, ssBoth);

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

Следующие свойства аналогичны определенным в TEdit — BorderStyle, HideSelection, MaxLength, OEMConvert и ReadOnly.

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


Компонент TMaskEdit

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomEdit -> TCustomMaskEdit -> TMaskEdit 

Модуль MASK

Страница Палитры компонентов Additional

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

Шаблон ввода в виде строки содержится в свойстве:

(РЬ) property EditMask: string;

Если он не определен, TMaskEdit работает как обычный редактор. Свойство

(Ro) property IsMasked: Boolean;

показывает, определен ли шаблон редактирования (значение EditMask не равно пустой строке).

"Черновой" текст, содержащий введенные пользователем символы, соответст­вует свойству:

property EditText: string;

В то же время отформатированный (наложенный на шаблон) текст содержится в свойстве Text.

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

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

Символ маскиОзначает, что на этом месте во вводимом тексте...
Lдолжна быть буква (A-Z, a-z, А-Я, а-я).
Iможет быть буква.
Адолжен быть буквенно-цнфровой символ.
аможет быть буквенно-цифровой символ.
Сдолжен быть любой символ ASCII.
сможет быть любой символ ASCII.
0должна быть любая цифра.
9может быть любая цифра.
#может быть любая цифра или знаки '+', •-'.
 

"Должен" означает, что пользователь обязан ввести в поле соответствующий символ, "может" — что не обязан. Например, шаблон "LLOO" обязывает поль­зователя ввести пароль из двух букв и двух цифр, a "LL99" — из двух букв и не более двух цифр.

Кроме описателей полей ввода, в шаблоне могут быть литералы и другие форматирующие символы.

Литералами будем называть символы, которые появляются при отображении строки ввода, но не могут изменяться пользователем и предназначены только для ее оформления. Перед литералом должен стоять символ 'V. Типичный пример — ввод телефонных номеров. Для семизначного номера с возмож­ностью ввода междугороднего кода нужен шаблон "!\(999\)000-0000;1;_". Тогда код города (если он есть) в отформатированном тексте будет заключен в скобки.

Специальные символы приведены в следующей таблице:

СимволЗначение
\Символ, непосредственно предшествующий литералу.
  Разделитель для часов, минут и секунд при вводе времени.
/Разделитель для дней, месяцев и лет при вводе даты.
\Разделитель полей в маске.
'Символ определяет подавление пробелов: если он есть в маске (в любом месте), в выходном тексте подавляются пробелы перед текстом; в противном случае — идущие после текста.
Символ, после которого все вводимые буквы преобразуются к верхнему регистру.
Символ, после которого все вводимые буквы преобразуются к нижнему регистру.
оПосле этой пары символов преобразование регистров отменяется.
-Пустое поле при вводе (отображается как пробел). Курсор не будет останавливаться в этой позиции.
 
Вторая часть шаблона — это символ '0' или '!', определяющий, записываются ли литералы в обработанный текст (свойство Text). При 0 символы опускаются. Использование такого компонента при работе с базами данных дает возмож­ность экономии места.

Например, пользователь ввел цифры 1234567. Тогда при действующем шаб­лоне "999\-99\-00;1;_" свойство Text будет равно "123-45-67", а для шаблона "999\-99\-00;0;_" - "1234567".

Третья часть содержит символ, который будет показываться в полях, пред­назначенных для ввода. Например, шаблон для ввода номеров машин "L 00\-00 LL;1;X" будет выглядеть как "X ХХ-ХХ XX". По умолчанию этот символ определяется значением константы DefaultBlank(cM. ниже).

Вторая и третья части шаблона могут отсутствовать.

Синтаксис шаблона может быть изменен за счет     переопределения прог­раммистом специальных символов '_'> ';' и '0'. Для этого нужно изменить определенные в модуле Mask константы:

const DefaultBlank: Char = '_';
MaskFieldSeparator: Char = ';';
MaskNoSave: Char = '0';

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

Непосредственную проверку введенного текста осуществляет метод:

procedure ValidateEdit;

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

Метод
function GetTextLen: Integer;
возвращает длину текста Text.

Функции для форматирования текста

Форматирование текста можно осуществить и без объекта класса TMaskEdit, при помощи описанных в модуле MASK функций:

function FormatMaskText(const EditMask: string; const Value: string): string;

— осуществляет форматирование строки Value по шаблону EditMask;

function MaskGetMaskSave(const EditMask: string): Boolean;

— возвращает значение True, если в обработанном тексте должны сохраняться литералы (соответствует значению второй части шаблона);

function MaskGetMaskBlank(const EditMask: string): Char;

— возвращает символ, который будет использоваться в шаблоне для запол­нения (третья часть шаблона);

function MaskGetFldSeparator(const EditMask: string): Integer;

— возвращает положение разделителя, отделяющего первую часть шаблона от последующих. Если он отсутствует, функция возвращает значение -1.



Оформление приложения

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


Компонент TPaintBox

TObject -> TPersistent -> TCornponent -> TControl -> TGraphicControl -> TPaintBox

Модуль EXTCTRLS

Страница Палитры компонентов System

Самой простой надстройкой над канвой служит компонент TPaintBox, пред­назначенный для рисования. Можно даже рассматривать его как канву, снаб­женную атрибутами компонента. Она представлена свойством:

(Ro) property Canvas: TCanvas;

Помимо канвы, компонент имеет свой цвет (фона)

(Pb) property Color: TColor;
и шрифт:
(Pb) property Font: TFont;

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

(Рb) property OnPaint: TNotifyEvent;


Компонент TShape

TObject -> TPersistent -> TComponent -> TControl -> TGraphicControl -> TShape

Модуль EXTCTRLS

Страница Палитры компонентов Additional

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

(Pb) property Shape: TShapeType;

Рисуемая фигура — одна из предопределенных в множестве:

TShapeType = (stRectangle, stSquare, stRoundRect, stRoundSquare, stEllipse, stCircle) ;

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

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

(Pk) property Brush: TBrush;
(Рb) property Pen: TPen;

Метод, исполняемый при изменении фигуры, кисти или пера

procedure StyleChangedfSender: TObject);

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


Компонент TBevel

TObject -> TPersistent -> TComponent -> TControl -> TGraphicControl -> TBevel

Модуль EXTCTRLS

Страница Палитры компонентов Additional

Этот элемент управления предназначен для выделения и разграничения облас­тей на форме. Может иметь вид прямоугольника или линии. Геометрическая форма компонента

(Pb) property Shape: TBevelShape;

может быть одной из принадлежащих множеству:

TBevelShape = (bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine, bsRightLine);
Стиль элемента — утопленный (bsLowered) или приподнятый (bsRaised) — определяется свойством:(Pb) property Style: TBevelStyle;
TBevelStyle = (bsLowered, bsRaised)

Этот компонент предназначен только для оформления — с ним не связаны никакие события.



Компонент TImage

TObject -> TPersistent -> TComponent -> TControl -> TGraphicControl -> TImage

Модуль EXTCTRLS

Страница Палитры компонентов Additional

Этот компонент служит надстройкой над классом TPicture и замыкает всю иерархию графических объектов VCL. Он предназначен для показа на форме изображения: битовой карты (TBitmap), метафайла (TMetafile), значка (TIcon).

Свойство
(Pb) property Picture: TPicture;

служит контейнером для графического объекта одного из перечисленных клас­сов.

В качестве канвы используется канва объекта Picture. Graphic — только если поле Graphic ссылается на объект класса TBitmap:

(Ro) property Canvas: TCanvas;

Если это не так, то попытка обращения к свойству вызовет исключительную ситуацию EInvalidOperation, так как рисовать на метафайле или значке нельзя. Будьте внимательны с этим свойством.

Следующие три свойства определяют, как именно Tpicture располагается в рабочей области компонента:

(Pb) property AutoSize: Boolean;

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

(Pb) property Stretch: Boolean;

— если это свойство установлено в True, то изображение "натягивается" на рабочую область, при необходимости уменьшая или увеличивая свои размеры. Если оно установлено в False, то играет роль следующее свойство;

(Pb) property Center: Boolean;

— если это свойство установлено в True, изображение центрируется в пределах рабочей области. В противном случае — располагается в ее верхнем левом углу.


 

Компонент TLabel

TObject -> TPersistent -> TCoinponent -> TControl -> TGraphicControl -> TCustomLabel -> TLabel
Модуль STDCTRLS
 
Страница Палитры компонентов Standard

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

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

(Pb) property Caption: TCaption;
TCaption = string[255];
Содержит строку с выводимым текстом.
(Pb) property Alignment: TAlignment;Устанавливает правило выравнивания текста — по правому, левому краю или по центру клиентской области.
(Pb) property AutoSize: Boolean;В случае True происходит автоматическое приведение размеров компонента к размерам текста и высоте шрифта.
(Pb) property ShowAccelChar: Boolean;Показывает, отображается ли в TLabel акселератор (символ, перед которым стоит знак амперсанда — '&'). Если оно равно False, амперсанд никак не интерпрети­руется. В случае True акселератор выделяется в строке подчеркиванием и нажатие клавиш <А11>+<символ> приводит к передаче фокуса окну FocusControl (т. к. TLabel сам не является оконным компонентом).
(Pb) property FocusControl: TWinControl;Определяет оконный компонент, которому посылаются сообщения о вводе акселе­ратора.
(Pb) property Transparent: Boolean;Прозрачность фона компонента. Если свойство установлено в True, то при перерисовке элемента управления не про­исходит закрашивание клиентской облас­ти. В противном случае — происходит закрашивание кистью bsSolid и цветом Color.
IPb) property WordMrap: Boolean;Определяет возможность разрыва слов в случае, если длина выводимого текста превышает ширину компонента.

 

Компонент THeader

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustoinControl -> THeader

Модуль EXTCTRLS

Страница Палитры компонентов Additional

Этот компонент представляет собой заголовок, например, ддя таблицы, т. е. совокупность расположенных горизонтально полей (секций) с текстом, ширина которых может изменяться.

Заголовок разделен на столько секций (столбцов), сколько строк имеется в свойстве:

(Pb) property Sections: TStrings;

Каждая строка отображается в своей секции. Если свойство:

(Pb) property AllowResize: Boolean;

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

(Pb) property SectionWidth[X: Integer]: Integer;

С изменением ширины секции связано два события. При каждом перемещении мыши во время изменения возникает событие:

(Pb) property OnSizing: TSeccionEvent;
TSectionEvent = procedure(Sender: TObject; ASection, AWidth:Integer) of object;

Оно означает, что произошло изменение ширины секции ASection и ее новая ширина равна AWidth. Об окончании изменения программист извещается при помощи события:

(Pb) property OnSized: TSectionEvent;

Стиль обрамления компонента обусловлен свойством:

(Pb) property BorderStyle: TBorderStyle; 

Ввод и выбор значений

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


Компонент TListBox

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomListBox -> TListBox

Модуль STDCTRLS

Страница Палитры компонентов Standard

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

(Pb) property Items: TStrings;

В списке Items. Strings хранится текст строк, а список Items.Objects пользователь может использовать для хранения связанных с ними объектов, например, картинок для нестандартно изображаемого списка.

Индекс текущего (сфокусированного) элемента списка содержится в свойстве:

property Itemlndex: Integer;

Не путайте сфокусированный элемент (стандартно он помещается в рамку из точек) и выделенный (цветным фоном), они могут не совпадать. Смысл этих понятий будет объяснен ниже. Значение индекса Itemlndex лежит в диапазоне от 0 до Items.Count-1. Он доступен для чтения и записи.

Индекс первого видимого элемента в списке представлен свойством:

property Toplndex: Integer;

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

Список выбора имеет свою канву:
(Ro) property Canvas: TCanvas;

и на его поверхности можно рисовать.

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

(Pb) property MultiSelect: Boolean;(Pb) property ExtendedSelect: Boolean;

Если MultiSelect установлено в False, то в списке одновременно не может быть выделено несколько элементов и значение ExtendedSelect не играет роли. В противном случае дело обстоит так. При ExtendedSelect = False каждый раз изменяется состояние только сфокусированного элемента. Каждый щелчок мышью или нажатие пробела меняет его состояние выделения на противопо­ложное. Если ExtendedSelect = True, то выбор происходит при передвижении мыши с нажатой левой кнопкой, каждом щелчке мышью на новом элементе списка при нажатых <Ctri> или <Shift>, или при нажатии <Shift>+<t/4 -> .

Количество выделенных элементов можно узнать из свойства:

(Ro) property SelCount: Integer; 

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

property Selected[Index: Integer]: Boolean;

При задании ошибочного индекса при доступе к списку возникает исключитель­ная ситуация EList Error.

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

(Pb) property Sorted: Boolean;

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

(Pb) property Columns: Integer;

Если столбец один, то значение этого свойства равно 0. Очистить список можно при помощи метода:

procedure Clear;

Стиль обрамления компонента определяется свойством:

(Pb) property BorderStyle: TBorderStyle;

Найти индекс элемента, которьш содержит точку Pos, можно при помощи метода:

function ItemAtPos(Pos: TPoint; Existing: Boolean): Integer; 

Параметр Existing определяет, что возвращается в случае неудачи (значение Items.Count либо -1).

Прямоугольник, отведенньш элементу списка с индексом Index, определяется с помощью метода:

function ItemRect(Index: Integer): TRect;

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

(Pb) property IntegralHeight: Boolean;

Если IntegralHeight равно False, то высота списка не изменяется. Это свойство не играет роли при стиле списка IbOwnerDrawVariable.

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

property Style;
TListBoxStyle = (IbStandard, IbOwnerDrawFixed, IbOwnerDrawVariable) ;

Рассмотрим назначение этого свойства более подробно.

В стандартном варианте (IbStandard) в списке отображаются только строки из свойства Items; в двух других случаях рисуемые пользователем списки могут иметь фиксированную (IbOwnerDrawFixed) или переменную (IbOwnerDrawVariable) высоту элемента. В первом случае нужно задать свойство:

(Pb) property ItemHeight: Integer;

Для стиля IbOwnerDrawVariable высота каждого элемента определяется прог­раммистом, которьш должен предусмотреть обработку события:

(Pb) property OnMeasureItem: TMeasureItemEvent;
TMeasureItemEvent = procedure(ListBox: TListBox; Index: Integer; var Height: Integer) of object;

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

Для рисования каждого элемента инициируется событие:

(Pb) property OnDrawItem: TDrawItemEvent;
TDrawItemEVent = procedure(ListBox: TListBox; Index: Integer;
Rect: TRect;
State: TOwnerDrawState) of object;

Обработчик этого события получает указатель на список ListBox, индекс эле­мента Index, отведенньш для рисования прямоугольник Rect, и состояние эле­мента в параметре State:

TOwnerDrawState = set of (odSelected, odGrayed, odDisabled,odChecked, odFocused) ;

Для списка выбора из этого множества действительны только флаги odSelected, odDisabled, odFocused.


Компонент TComboBox

TObject -> TPersistent -> TComponent -> TControl -> TWinControl ->  -> TCustomCornboBox -> TComboBox

Модуль STDCTRLS

Страница Палитры компонентов Standard

Этот стандартный элемент управления Windows — комбинированный список -— имеет много общего с TListBox. Он состоит из собственно списка и помещен­ного рядом поля ввода редактирующего элемента. Таким образом, пользова­тель может выбрать одно из готовых значений какой-то величины или ввести свое. Стиль компонента в части правил взаимного сочетания списка и редак­тора определяется свойством:

property Style: TComboBoxStyle;
TComboBoxStyle = (csDropDown, csSimple, csDropDownList, csOwnerDrawPixed, csOv'nerDrawVariable);

Его значения имеют следующий смысл:

  • csSimple — весь список виден все время. Текущий выбор отображается в редакторе, его можно изменить;
  • csDropDown — список открывается (выпадает) и скрывается при нажатии кнопки, расположенной справа от текста. Такой список будем называть вьша дающим;
  • csDropDownList —список вьшадающий, но редактирующий элемент заме­нен статическим текстом и вводить свои данные пользователь не может;
  • csOwnerDrawFixed — определяемьш пользователем стиль списка с по­стоянной высотой элемента;
  • csOwnerDrawVariable — определяемьш пользователем стиль списка с пере­менной высотой элемента.

Принципы пользовательской отрисовки списка для csOwnerDrawFixed и csOwnerDrawVariable, а также связанные с этим методы и события остались такими же, как в TListBox. По умолчанию устанавливается сталь csDropDown.

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

(Pb) property Items: TStrings;
property Itemlndex: Integer;procedure Clear;
(Pb) property Sorted: Boolean;
(RcS)
property Canvas: TCanvas;

Текст, содержащийся в редактирующем элементе списка, доступен через свой­ство:

property Text: TCaption;

Его максимальная длина ограничена числом символов, равным значению свой­ства:

(Рb) property MaxLength: Integer;

Если MaxLength равно 0, то ограничений на длину строки нет (до 255 сим­волов). При изменении текста (а также при смене выбранного элемента) возникает событие OnChange. Часть текста может быть выделена. Три свойства содержат выделенный текст, его положение и длину:

property SelText: string;
property SelStart: Intege;
property SelLength: Integer;
Метод
procedure SelectAll; 

выделяет весь текст. Значение свойства

property DroppedDown: Boolean;

соответствует состоянию списка: True соответствует открытому ("выпавшему") списку. С его помощью можно показывать или скрывать список из программы. При изменении состояния списка возникает событие:

(Рb) property OnDropDown: TNotifyEvent ;

Максимальное число элементов, которые показываются при выпадении списка:

(Pb) property DropDownCount: integer;

По умолчанию оно равно 8. В первой версии VCL это свойство описано, но не реализовано (не играет роли).


Компонент TScrollBar

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TScrollBar

Модуль STDCTRLS

Страница Палитры компонентов Standard

TScrollBar представляет собой стандартный бегунок Windows. В таблице перечислены свойства этого компонента:

(Pb) property Kind: TScrollBarKind; ScrollBarKind = (sbHorizontal, sbVertical) ;Задает один из предопределенных типов бегунка: горизонтальный (по умолчанию) или вертикальный.
(Pb) property Max: Integer;Максимальное значение положения бегунка.
(Pb) property Min: Integer;Минимальное значение положения бегунка.
(РЫ property Position: Integer;Текущее положение бегунка.
procedure SetParams(APosition, AMin, AMax: Integer);Устанавливает сразу положение и пределы из­менения бегунка. Если AMax<AMin, возникает исключительная ситуация EInvalidOperation.
(РЙ property LargeChange: TScrollBarInc; TScroll Bar Inc=l...32767;"Большой" сдвиг бегунка. Применяется при перемещении на одну страницу. Осу­ществляется при щелчке мышью по поверх­ности компонента с соответствующей стороны или при нажатии <PgUp> или <PgDn>.
(рь)property SmallChange: TScrollBarInc;"Малый" сдвиг бегунка. Применяется при перемещениях на одну линию: при щелчке на кнопках со стрелками на концах бегунка или нажатии клавиш управления курсором.
 
Событие
(Pb) property OnScroll: TScrollEvent;
TScrollEvent = procedure(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer) of object;

вызывается при каждом изменеюш положения бегунка. Обработчик же события OnChange вызывается внутри метода SetParams при изменении значений Мах, Min и Position. ScrollCode — вид перемещения бегунка:

TScrollCode = (scLineUp, scLineDown, scPageUp, scPageDown, scPosition, scTrack, scTop, scBottorn, scEndScroll);
  • scLineUp, scLineDown — на строку вверх/вниз;
  • scPageUp, scPageDown — на страницу вверх/вниз;
  • scPosition, scTrack — в заданную позицию;
  • scTop, scBottom — в крайнее верхнее/нижнее положение;
  • scEndScroll — извещает об окончании процесса прокрутки.

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


Компонент TSpinEdit

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomEdit -> TSpinEdit

Модуль SPIN

Страница Палитры компонентов Samples

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

(Ro) property Button: TSpinButton;Содержит указатель на кнопку, через который можно обратиться к ее свойствам и методам.
(Pb) property EditorEnabled: Boolean;В состоянии False запрещает изменение значений в редакторе.
(Pb) property Readonly: Boolean;В состоянии False полностью запрещает изменение значений (при помощи кнопок и редактора).
(Pb) property MinValue: Longint;Содержит минимальное допустимое значение.
(pb) property MaxValue: Longint;Содержит максимальное допустимое значение.
(Pb) property MaxLength: Integer;Содержит значение максимального количества символов (цифр, знаков '-' и '+')в редакторе.
(fb) property Increment: Longint;Содержит величину, на которую изменяется значение в редакторе при каждом нажатии кнопки.
(Pb) property Value: Longint;Содержит текущее значение.

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

(Pb) property OnClick: TNotifyEvent;
(РЕ) property OnDblClick: TNotifyEvent;

Если щелчок произошел над областью кнопки, то возникают специфические для нее события OnUpClick или OnDownClick, а в самом компоненте только отражается произошедшее изменение:

(Pb) property OnChange: TNotifyEvent;

Событие OnChange возникает также при редактировании текста (если оно не запрещено). Если нажать и не отпускать одну из кнопок, то в это время соответствующие события происходят периодически (период 400 мс).



Создание таблиц и иерархических структур

В эту группу входят только три компонента — TDrawGrid, TStringGrid и TOutline. Это, если можно так выразиться, элементы управления "второго поколения" — они решают гораздо более сложные задачи, чем традиционный набор средств Windows, но при этом и устроены намного сложнее.


Компонент TDrawGrid

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomControl -> TCustomGrid -> TDrawGrid

Модуль GRIDS

Страница Палитры компонентов Additional

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

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

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

Свойства TDrawGrid, определяющие его внешний вид, приведены в таблице:
 
(pb) property ColCount: Longint;
(Pb) property RowCount: Longint;
Содержат количество строк и столбцов в таблице. Обратите внимание, что координаты ячеек в таблице имеют тип Longint, т. е. в принципе число строк и(или) столбцов может превышать 65535.
property Col:Longint;
property Row: Longint;
Содержат номера столбца и строки, содержащих сфокусированную ячейку.
property ColWidths[Index: Longint]: Integer; property RowHeights[Index: Longint]: Integer;Свойства-массивы, содержащие ширину каждого столбца и высоту каждой строки. (Ширина и высота ячеек могут быть индивидуальными, см. свойство Options.)
property DefaultColWidth: Integer;
property DefaultRowHeight: Integer;
Содержат ширину столбца и высоту строки, принимаемые по умолчанию. Они применяются при начальной инициали­зации таблицы и при добавлении в нее ячеек.
(Ro) property GridHeight: Integer;
(Ro) property GridWidth: Integer;
Содержат высоту и ширину всей таблицы. Эти свойства доступны только для чтения, так как являются производными от числа ячеек и их размеров.
(Pb) property ScrollBars: TScrollStyle;
TScrollStyle = (ssNone, ssHorizontal, ssVerticai, ssBoth) ;
Задает полосу прокрутки. Если все ячейки не помещаются в область, отведенную компоненту, появляются полосы прокрут­ки в нужном направлении. По умолчанию предусмотрены обе полосы прокрутки.
property FixedCols: Integer;
property FixedRows: Integer;
Содержат соответственно число строк и столбцов в фиксированной области.
(Pb) property FixedColor: TColor;Содержит цвет, которым происходит закрашивание ячеек фиксированной области.
property TopRow: Longint; property LeftCol: Longint;Содержат номера верхней строки и левого столбца, видимых в подвижной области. Первоначально это первая ячейка за фик­сированной областью (TopRow = FixedRows, LeftCol = FixedCols), однако при прокрутке и других перемещениях сфокусированной ячейки эти значения могут изменяться. Свойства доступны только во время исполнения.
(Pb) property OnTopLeftChanged: TNotifyEvent;Событие вызывается, когда изменяются TopRow или LeftCol.
property VisibleColCount: Integer;
property VisibleRowCount: Integer;
Содержат соответственно число полностью видимых столбцов и строк в подвижной области. Могут быть не полностью видны еще один столбец и одна строка.

Рассматриваемый компонент имеет множество вариантов настройки под кон­кретное применение. Изменить его функционирование вы можете, настроив соответствующим образом опции:

(Pb) property Options: TGridOptions;
TGridOption = (goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goDrawFocusSelected, goRowSizing, goColSizing, goRowMoving, goColMoving, goEditing, goTabs, goRowSelect, goAlwaysShowEditor, goThumbTracking);
TGridOptions = set of TGridOption;

В множестве допускаются сочетания следующих опций:

  • goFixedVertLine — ячейки в фиксированной области разделяются вертикальными линиями;
  • goFixedHorzLine — ячейки в фиксированной области разделяются горизон­тальными линиями;
  • goVertLine — ячейки разделяются вертикальными линиями;
  • goHorzLine — ячейки разделяются горизонтальными линиями;
  • goRangeSelect — может быть выделено множество ячеек;
  • goDrawFocusSelected — при наличии опции ячейка, имеющая фокус, рисуется тем же цветом, что и выделенная. В противном случае — имеет цвет обычных ячеек (но выделяется, как всегда, рамкой из отдельных точек);
  • goRowSizing — высота строк может изменяться индивидуально;
  • goColSizing — ширина столбцов может изменяться индивидуально;
  • goRowMoving — строки могут быть перемещены мышью;
  • goColMoving — столбцы могут быть перемещены мышью;
  • goEditing — ячейки таблицы могут редактироваться;
  • goAlwaysShowEditor — содержимое активной (сфокусированной) ячейки всегда загружается в редактор (в противном случае требуется нажатие <F2> или щелчок мышью);
  • goTabs — переход между столбцами возможен при помощи табуляции (<ТаЬ> или <Shift>+<Tab);
  • goRowSelect — если эта опция присутствует, в таблице нельзя выделить единственную ячейку (кроме левой нижней из видимых). Выделяется всегда текущий столбец или область ячеек от левой нижней до текущей;
  • goThumbTracking — задает поведение ячейки при передвижении мышью бегунка полосы прокрутки. Если эта опция отсутствует, содержимое ячеек не обновляется, пока пользователь не отпустит кнопку мыши; иначе — перерисовка происходит при каждом изменении.

Толщина линий, разделяющих ячейки таблицы, задается свойством:

(Pb) property GridLineWidth: Integer;

Линии в вертикальном и горизонтальном направлениях рисуются в случае наличия опций [goFixedVertLine, goVertLine] и [goFixedHorzLine, goHorzLine] соответственно.

Метод
function CellRect(ACol, ARow: Longint): TRect;

возвращает прямоугольник, соответствующий ячейке с индексами ACol, ARow в системе координат клиентской области таблицы. Метод MouseToCell превращает координаты точки нажатия кнопки мыши в индексы строки и столбца, где оно произошло:

procedure MouseToCell (X, Y: Integer; var ACol, ARow: Longint);

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

В сфокусированной ячейке редактор ячеек таблицы можно вызвать вводом любого символа ASCII или <F2>. Указывает, активен ли редактор, свойство:

property EditorMode: boolean;

Оно не имеет смысла, если редактор активен постоянно (установлена опция goAlwaysShowEditor).

Если установлен режим goTabs, то между столбцами таблицы можно передвигаться, нажимая <Таb> или <Shift>+<Tab>. По умолчанию фокус будет останавливаться на всех столбцах. Чтобы исключить остановку на некоторых столбцах, нужно присвоить значение False элементу массива TabStops с нужным индексом:

(Pb) property TabStops[Index: Longint]: Boolean;

He путайте это свойство с TabStop, которое касается всего компонента. Событие, возникающее при смене сфокусированной ячейки:

(Pb) property OnSelectCell: TSelectCellEvent;
TSelectCellEvent = procedure (Sender: TObject; Col, Row: Longint; var CanSelect: Boolean) of object;

Фокус должен переместиться в ячейку (Col, Row). Изменяя значение параметра CanSelect, можно запретить перемещение фокуса в некоторые ячейки.

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

property Selection: TGridRect;TGridRect = recordcase Integer of 
0: (Left, 'I'op, Right, Bottom: Longint);
1: (TopLeft, BottomRight: TGridCoord);
end;TGridCoord = recordX: Longint;Y: Longint;end;

Стиль обрамления всей таблицы задается:

(Pb) property BorderStyle: TBorderStyle;
При bsSingle компонент окаймляется черной линией.

Перейдем к тому, как помещать и отображать информацию в ячейки TDrawGrid.

Если вы вводите текст, то он виден в редакторе, возникшем в текущей ячейке. Но как только ввод завершен, текст исчезает. Почему? TDrawGrid возлагает на программиста обязанность нарисовать содержимое каждой ячейки. Если свойство

(Pb) property DefaultDrawing: Boolean;

установлено 6 True, для всех состояний ячеек предусматривается отрисовка по умолчанию, а именно заливка ячейки определенным для данного состояния цветом. Только установив его в False, программист получает доступ к обработке событий OnDrawCell и может изобразить каждую ячейку таблицы так, как ему требуется. Для этого таблица имеет свою канву:

property Canvas: TCanvas;

Обработчик события OnDrawCell должен иметь тип:

(Pb) property OnDrawCell: TDrawCellEvent;
TDrawCellEvent = procedure (Sender: TObject; Col, Row: Longint; Rect: TRect; State: TGridDrawState) of object;

Параметры:

  • Col, Row — координаты (номера столбца и строки) ячейки;
  • Rect — отведенный ей прямоугольник;
  • State — состояние ячейки. Описывается флагами из множества:
    TGridDrawState = set of (gdSelected, gdFocused, gdFixed); 

Флаги соответствуют выбранной, сфокусированной ячейкам и ячейке из фиксированной области. Приведенный ниже фрагмент кода закрашивает ячейки таблицы разным цветом в зависимости от значений во внешнем массиве Field:

procedure TFormI-DrawGridlDrawCell(Sender: TObject; Col, Row: Longint;Rect: TRect; State: TGridDrawState);
begin
    with DrawGridI.Canvas do
    begin
        if Field[Col,Row] then
            Brush.Color := clAqua
        else
            Brush.Color := clBackground;
        FillRect(Rect);
    end;
end;

При установленных опциях goColMoving/goRowMoving можно захватить мьппью ячейку заголовка (в фиксированной области) и перенести всю строку или столбец на другое место. В этом случае после нажатия левой кнопки мыши появляется вертикальная или горизонтальная линия, показывающая, куда будет вставлена перемещаемая информация: при движении к началу таблицы — за линией, к концу — перед ней. При этом корректируются раз­меры выделенной области. Строки и столбцы заголовков, полностью лежащие в фиксированной области, переносить нельзя.

По окончании переноса происходят события, которые информируют о пере­мещении столбца или строки из положения Fromlndex в положение Tolndex:

(pb) property OnColumnMoved: TMovedEvent ;(Pb) property OnRowMoved: TMovedEvent;
TMovedEvent = procedure (Sender: TObject; Fromlndex, Tolndex: Longint) of object;

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

параметре Value обработчика события OnGetEditMask. Напомним, что редак­тор ячейки таблицы является потомком TMaskEdit:

(Pb) property OnGetEditMask: TGetEdiCEvent;
TGetEditEvent = procedure (Sender: TObject; ACol, ARow: Longint; var Value: string) of object;

Далее редактор извлекает текст, связанный с ячейкой. При этом вызывается событие:

(Pb) property OnGetEditText: TGetEditEvent;

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

При каждом изменении текста в редакторе инициируется событие:

(Pb) property OnSetEditText: TSetEditEvent; 
TSetEditEvent = procedure (Sender: TObject'; ACol, ARow: Longint; const Value: string) of object;

Иллюстрирует применение TDrawGrid пример LIFE. Это классическая игра "жизнь" (автор — X. Конвей), имитирующая законы выживания. Каждая ячей­ка таблицы здесь соответствует одному "существу". Его состояние изменяет­ся через некоторые интервалы времени (для этого используется компонент TTimer). Существо "живет" нормально, если у него двое или трое соседей. Если их меньше, оно умирает от одиночества, если больше — от перенаселения. Новая жизнь появляется в пустой ячейке, если у нее ровно трое соседей. Начальное состояние ячеек может быть случайным, а может быть задано вами:

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


 

Компонент TStringGrid

TObject -> TPersistent -> TComponent-*TControl -> TWinControl ->   -> TCustomControl -> TCustomGrid -> TDrawGrid -> TStringGrid 

Модуль GRIDS

Страница Палитры компонентов Additional

Этот компонент реализует возможности своего предка TDrawGrid применитель­но к таблице строк.

В состав компонента добавлен объект класса TStrings, в котором хранится содержимое ячеек. Он доступен как векторное свойство — двумерный массив текстовых строк (размерностью ColCount x RowCount), соответствующих ячей­кам таблицы:

property Cells[ACol, ARow: Integer]: string;

Доступен и двумерньш массив объектов, соответствующих ячейкам:

property Objects[ACol, ARow: Integer]: TObject;

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

Можно работать отдельно как со строками, так и со столбцами таблицы. Свойства

property Cols[Index: Integer]: TStrings;
property Rows[Index: Integer]: TStrings;

описывают наборы строк (также в виде TStrings), содержащие текст и объекты столбцов и строк таблицы.

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

Отметим, что перенос строк и столбцов таблицы (при установленных опциях goColMoving или goRowMoving) осуществляется вместе с их текстовыми стро­ками.


 

Компонент TOutline

TObject -> TPersistent -> TCoinponent -> TControl -> TWinControl -> -> TCustomControl -> TCustomGrid -> TCustomOutline -> TOutline 

Модуль OUTLINE

Страница Палитры компонентов Additional

TOutline создан для ведения и отображения иерархических структур данных — деревьев. Это один из наиболее сложных и интересных компонентов. В этот раздел он попал потому, что является потомком таблицы (TCustomGrid), хотя и мало чем ее напоминает.

Типичным примером применения TOutline можно назвать отображение структуры файловой системы (для этого даже есть отдельный компонент TDirectory Outline). В описанном ниже примере OBJTREE этот компонент используется для отображения дерева классов библиотеки VCL.

Дерево состоит из элементов (будем называть их узлами), упорядоченных по уровням. Каждый из них имеет родительский узел (на более высоком уровне) и список дочерних узлов-потомков. Исключением являются корневой узел (ну­левого уровня) — он не имеет предка, и узлы последнего уровня, не имеющие потомков.

Каждый узел является объектом класса TOutlineNode:

TOutlineNode = class(TPersistent) 

Рассмотрим сначала методы и свойства этого объекта. С каждым узлом можно связать информацию — имя и произвольные данные:

property Text: string;property Data: Pointer;

Указатель на родительский узел определяется свойством:

(Ro) property Parent: TOutlineNode;

Если список дочерних узлов не пуст, что можно проверить при помощи свой­ства

(Ro) property Hasltems: Boolean;

то для получения информации о них есть метода,!:

function GetFirstChild: Longint;
function GetLastChild: Longint;
function GetNextChild(Value: Longint): Longint;
function GetPrevChiId(Value: Longint): Longint;

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

(Ro) property Index: Longint;

Используя его, можно получить указатель на узел (см. ниже сам компонент TOutline). Узлы пронумерованы таким образом, что если родитель имеет номер N, то первый из его потомков — номер (N+1).

Можно узнать и полное имя (путь) узла, представляющее собой конкатенацию всех родительских имен и имени узла, разделенных специальным символом. Этот символ определен в свойстве ItemSeparator объекта TCustomOutline, ко­торому принадлежат узлы. Полный путь определяется свойством:

(Ro) property FullPath: string;

Каждый узел расположен на своем иерархическом уровне. На самом верху находится узел уровня 0. Все другие являются для пего дочерними; он не виден и не доступен пользователю. Поэтому на первом доступном уровне — с номером 1 — могут находиться по вашему желанию один или несколько узлов. Уровень иерархии узла можно узнать в его свойстве:

(ro)property Level: Cardinal;

Чтобы изменить уровень, надо вызвать метод:

procedure ChangeLevelBy(Value: TChangeRange);

которьш перемещает узел в список другого уровня. Диапазон перемещения TChangeRange ограничен:

TChangeRange = -1..1;

Чтобы переместить узел в дереве, нужно вызвать следующий метод

procedure MoveTo(Destination: Longint; AttachMode: TAttachMode);
TAttachMode = (oaAdd, oaAddChild, oalnsert);

Он перемещает узел (вместе со всеми потомками) в положение с индексом Destination. Родительский узел не может переместиться на место любого из своих потомков. Режим перемещения AttachMode означает:

  • oaAdd — добавить последним на том же уровне, что и Destination;
  • oaAddChild — добавить последним к потомкам узла Destination;
  • oalnsert — заменить в положении Destination прежний узел, которьш сме­щается дальше по списку на том же уровне.

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

(Ro) property Topltem: Longint;

Для корневого узла это свойство равно 0.

Компонент TOutline не только хранит древовидную структуру, он еще и отоб­ражает ее. На экране каждый узел может находиться в двух состояниях, свернутом и развернутом. В свернутом состоянии потомки узла не видны, в раз­вернутом они изображаются чуть ниже и правее друг под другом. Состояние узла может иллюстрироваться значком (плюс/минус, открытая/закрытая папка — см. описание свойства OutlineStyle компонента TOutline). В таблице приведены методы и свойства, управляющие состоянием узла на экране:

property Expanded: Boolean;Указывает, в каком состоянии находится узел; True — развернутое состояние.
procedure Collapse;Сворачивает узел, пряча все дочерние узлы.
procedure Expand;Разворачивает узел списка, показывая дочерние узлы.
procedure FullExpand;Полностью разворачивает узел, показывая все дочерние узлы всех подуровней.
 

Сворачивать/разворачивать узлы дерева, помимо    щелчков мышью, можно нажатием клавиш:

  • <+> — соответствует Expand;
  • < -> — соответствует Collapse;
  • <*> — соответствует FullExpand.
Свойство
(Ro) property IsVisible: Boolean;

означает, может ли быть виден узел. Это возможно только в том случае, если виднь! все его родители. При отрисовке ширина узла сообщается методом:

function GetDisplayWidth: Integer;

Теперь перейдем от описания узла к описанию самого дерева — компонента TOutline. Он представляет собой совокупность узлов типа TOutlineNode. Всего в дереве содержится число узлов, равное значению свойства:

(Ro) property ItemCount: Longint;

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

(Ro) property Items[Index: Longint]: TOutlineNode;

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

property Selectedltem: Longint;

Например, выполнение оператора

Items[Items[Selectedltem].Topltem].FullExpand;

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

property Row: Longint;

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

function GetDataItem(Value: Pointer): Longint;function GetTextItem(const Value: string): Longint; 

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

function GetItemfX, Y: Integer): LongInC;

Целых три пары методов добавляют новый узел в дерево. Его имя инициализируется параметром Text. Различие между первым и вторым мето­дами в парах в том, что второй позволяет связать с узлом данные (параметр Data), а в первом вместо них записывается nil.

function Add(Index: Longint; const Text: string): Longint;function AddObject(Index: Longint; const Text: string;const Data: Pointer): Longint;

— добавляют новый узел в качестве последнего в тот же список, где находится узел Index. Поскольку на самом верху иерархии может быть только один узел, то в случае задания Index = 0 он добавляется в список верхнего уровня. Соответствуют режиму oaAdd;

function AddChild(Index: Longint; const Text: string): Longint;
function AddChildObject(Index: Longint; const To: string; const Data: Pointer): Longint;

— добавляют новый узел в качестве последнего потомка узла Index. Соответ­ствуют режиму oaAddChild;

function Insert(Index: Longint; const Text: string): Longint;
function InsertObject(Index: Longint; const Text: string;const Data: Pointer): Longint;

— вставляют узел в положение Index. При этом прежний узел с таким индексом и все другие на этом уровне сдвигаются вниз. Единственное исключение — задание в качестве параметра нулевого индекса. В этом случае узел добавляется последним в список самого верхнего уровня. Соответствуют режиму oalnsert. Все методы вызывают переиндексирование дерева и возвращают уже новый индекс для вставленного узла. Если нужно удалить узел, то метод

procedure Delete(Index: Longint);
удаляет узел с индексом Index, а метод
procedure Clear;
очищает все дерево.

Если нужно вставить или удалить сразу много узлов и при этом избежать трудоемких операций переиндексации и перерисовки дерева, то соответству­ющий код надо заключить между вызовами методов:

procedure BeginUpdate;procedure EndUpdate;

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

procedure SetUpdateSCate(Value: Boolean);

Дерево можно полностью свернуть или полностью развернуть вызовом мето­дов:

procedure FullExpand;procedure FullCollapse;

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

(pb) property OnExpand: EOutlineChange;
(Рb) property OnCollapse: EOutlineChange;
EOutlineChange= procedure (Sender: TObject; Index: Longint) of object;
где параметр Index означает индекс узла, изменившего состояние. Метод
function GetNodeDisplayWidth(Node: TOutlineNode): Integer;

возвращает ширину, занимаемую изображением узла (если установленньш стиль не osOwnerDraw, см. ниже).

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

procedure LoadFromFile(const FileName: strings-procedure LoadFromStream(Stream: TStream);
procedure SaveToFile(const FileName: strings-procedure SaveToStream(Stream: TStream);

Для прокрутки информации TOutline по умолчанию имеет обе полосы, опре­деляемые свойством:

(Pb) property ScrollBars: TScrollStyle;
TScrollStyle = (ssNone, ssHorizontal, ssVertical, ssBoth);

Строка (символ), разделяющий имена узлов при составлении полного имени узла, содержится в свойстве:

(Pb) property ItemSeparator: string;

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

(Pb) property Lines: TStrings;

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

(Pb) property PicturePlus: TBitmap;Соответствует свернутому узлу. По умолчанию — "плюс".
(Pb) property PictureMinus: TBitmap;Соответствует развернутому узлу. По умолчанию — "минус".
(Pb) property PictureOpen: TBitmap;Соответствует развернутому узлу. По умолчанию — "открытая папка".
(Pb) property PictureClosed: TBitmap;Соответствует свернутому узлу. По умолчанию — "закрытая папка".
(Pb) property PictureLeaf: TBitmap;Соответствует "листу" — узлу без потомков. По умолчанию — "документ".
 

Желательно, чтобы картинки имели "прозрачный" фон, то есть чтобы их свойство TransparentColor соответствовало цвету рабочей области компонента. Эти пиктограммы можно переопределить в случае необходимости.

Свойство OutlineStyle определяет, в частности, когда и какие пиктограммы будут показаны:

(Pb) property OutlineStyle: TOutlineStyle;
TOutlineStyle = (osText, osPlusMinusText, osPictureText, osPlusMinusPictureText, osTreeText, osTreePictureText);

В зависимости от значения этого свойства изображаются:

  • osText — только текст;
  • osPlusMinusText — текст и пиктограммы PicturePlus и PictureMinus в зависимости от состояния узла. "Лист" не имеет значка;
  • osPictureText — текст и пиктограммы PictureOpen, PictureClosed и PictureLeaf в зависимости от состояния узла;
  • osPlusMinusPictureText — объединяет в себе два предыдущих стиля;
  • osTreeText — текст и специальные линии, иллюстрирующие связь между родительским и дочерними узлами;
  • osTreePictureText — объединяет в себе стили osTreeText и osPictureText. По умолчанию установлен стиль osTreePictureText;

На внешний вид дерева влияют и опции, содержащиеся в свойстве:

(Pb) property Options: TOutlineOptions;
TOutlineOption = (ooDrawTreeRoot, ooDrawFocusRect, ooSCretchBitmaps);
TOutlineOptions = set of TOutlineOption;

Это множество может содержать элементы:

  • ooDrawTreeRoot — задает соединение линией всех узлов верхнего уровня. В случае отсутствия опции каждый из них выглядит как вершина от­дельного дерева. Эта опция играет роль только для стилей osTreeText, osTreePictureText;
  • ooDrawFocusRect — задает выделение сфокусированного узла рамкой из точек;
  • ooStretchBitmaps — задает приведение размеров пиктограмм к размерам шрифта текста путем масштабирования. В противном случае либо из пиктограммы вырезается часть (если она больше), либо остается свободное место (если меньше).

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

property Style: TOutlineType;
TOutlineType = (otStandard, otOwnerDraw);

Стиль osStandard подразумевает, что дта каждого узла будет изображено то, что предусмотрено стилем OutlineStyle. Для реализации стиля otOwnerDraw нужно нарисовать содержимое узла в обработчике события:

(Pb) property OnDrawItern: TDrawItemEvent;
TDrawItemEvent = procedure(ListBox: TListBox; Index: Integer;
Rect: TRect; State: TOwnerDrawState) of object;
Параметры:
  • Index — индекс узла;
  • Rect — отведенный ему прямоугольник;
  • State — множество, в которое могут входить состояния odSelected, odFocused.

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

(Pb) property ItemHeight: Integer;

Для рисования у компонента есть своя канва:

property Canvas: TCanvas ;

Установить ее можно только для объекта стиля osOwnerDraw; при osStandard канва игнорируется.

Обрамление компонента задается свойством:

(Pb) property BorderStyle: TBorderStyle;

Разобраться с применением этого компонента поможет пример OBJTREE. В нем по заранее заданному массиву компонентов ClassesSet выстраивается иерархическое дерево, в которое добавляются и все объекты-предки. Для примера были выбраны только 32 компонента, при желании можно включить и все остальные. Не забывайте при этом добавить содержащие их модули к тем, что содержатся в операторе uses. Когда вы перемещаете фокус по дереву, отображается имя объекта и имя модуля, в котором он описан. Для этого используется информация, возвращаемая недокументированным (пока?) мето­дом класса TObject.ClassInfo. Возвращаемая им структура описана в исходных текстах VCL.


Многостраничные диалоговые окна

Во многих сложных программных комплексах сейчас предусмотрены десятки, а то и сотни параметров, которые может (должен!) устанавливать пользователь. Это означает либо перегруженность диалоговых окон, либо слишком большое их число. Выходом из этого положения стало повсеместное внедрение мно­гостраничных диалогов-"блокнотов".

Для создания таких диалогов в VCL предназначены компоненты TNotebook, TTabSet и TTabbedNotebook.


Компонент TNotebook

TObject ->TPersistent -> TComponent -> TControl -> TWinControl -> TCustoinControl -> TNotebook

Модуль EXTCTRLS

Страница Палитры компонентов Additional

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

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

(Pb) property ActivePage: string; 

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

property Pagelndex: Integer;

Для реакции при изменении текущей страницы предусмотрено свойство:

(Pb) property OnPageChanged: TNotifyEvent;
В свойстве
(Pb) property Pages: TStrings; 

содержится вся информация о страницах. Напомним, что в классе TStrings есть два основных списка: через список Pages.Strings можно обратиться к именам страниц, а через список Objects — непосредственно к объектам-страницам. Опубликованными свойствами страницы являются Caption, Height, Width, Visible и TabOrder.Используя методы компонента TStrings, можно добавлять и удалять страницы, проводить поиск и т. п. В конструкторе ком­понента TNotebook список инициализируется единственной страницей с именем 'Default'.

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

Procedure TForm1.OpenlClick(Sender: TObject);
var
    Animage : TImage;
    AScrollBox: TScrollBox;
    i: integer;
begin
    OpenDialog1.Filter := GraphicFilter(TGraphic);
    if not OpenDialogI.Execute then
        Exit;
    Animage := TImage.Create(Self);
    with Animage do
    begin
        Picture.LoadFroinPile (OpenDialog1.FileName);
        AutoSize := True;
        Visible := True;
    end;
    AScrollBox := TScrollBox.Create(Self);
    with AScrollBox do
    begin
        Align := alClient;
        Visible := True;
    end;
    with Notebookl do
    begin
        Pages.Add(ExtractFileName(OpenDialog1.FileName));
        Animage.Parent := AScrollBox;
        AScrollBox.Parent:= Pages.Objects[Pagelndex] as TPage;
        i := Pages.IndexOf('Default');
        if i >= 1 then Pages.Delete(i);
        TabSetl.Tabs := Pages;
        TabSetl.TabIndex := Pages.Count - 1;
    end;
end;
В этом примере компонент TNotebook взаимодействует с TTabSet — вместе они составляют блокнот.
 

Компонент TTabSet

TObject -> TPersistent -> TCoinponent -> TControl -> TWinControl -> TCustornControl -> TTabSet

Модуль TABS

Страница Палитры компонентов Additional

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

Как бы ни был выровнен TTabSet, закладки появляются таким образом, что они как бы "приклеены" к его верхнему краю. Поэтому этот компонент располагают снизу от TNotebook или другого компонента, отображающего информацию.

Строки, содержащие текст, который появится на закладках, описаны свойством:

(Pb) property Tabs: TStrings;

Строки (т. е. закладки) можно добавлять и удалять, все это отобразится в процессе исполнения. В отличие от TNotebook, список Objects свойства Tabs не используется, и программист может привязать к каждой закладке какой-нибудь объект, например, пиктограмму (см. ниже стиль tsOwnerDraw).

Индекс активной (выделенной) в данный момент закладки доступен для чтения и записи через свойство:

property Tablndex: Integer;

Отсчет начинается от 0 и заканчивается на Tabs.Count-1. Если ни одна закладка не выделена, Tablndex равен -1.

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

(Pb) property OnChange: TTabChangeEvent;
TTabChangeEvent = procedure(Sender: TObject; NewTab: Integer; var AllowChange: Boolean) of object;

Узнав предполагаемый новый индекс (NewTab), изменение можно запретить (установив параметр AllowChange в False).

Сменить текущую закладку можно и из программы, вызвав метод:

procedure SelectNext(Direction: Boolean); 

Параметр Direction, равный True, означает увеличение индекса на 1, False — соответствующее уменьшение. При этом набор циклически замкнут — после последней закладки будет выбрана первая (с нулевым индексом) и т. д.

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

(Pb) property AutoScroll: Boolean;

установлено в True. В противном случае доступ к невидимым закладкам нужно осуществлять программно.

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

(pb) property StartMargin: Integer;(Pb) property EndMargin: Integer;

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

property Firstlndex: Integer;

При этом одновременно видно столько закладок, сколько определено в свой­стве:

(Ro) property VisibleTabs: Integer;

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

function ItemAtPos(X, Y: Integer): Integer;

а узнать координаты отведенного ей прямоугольника — через вызов метода:

function ItemRect(Item: Integer): TRect;

Какими средствами изображается компонент? Это определяется его стилем:

(Pb) property Style: TTabStyle;
TTabStyle = (tsStandard, tsOwnerDraw) ;

Стиль tsStandard подразумевает вывод на закладке ее названия стандартными средствами. Если программист хочет изобразить на ней нестандартную инфор­мацию, например, пиктограмму или произвольный текст, он должен установить стиль tsOwnerDraw. Для правильного изображения таких закладок нужно пре­дусмотреть обработчики двух событий — OnMeasureTab и OnDrawTab. Первое из них имеет тип:

(Pb) property OnMeasureTab: TMeasureTabEvent;
TMeasureTabEvent = procedure(Sender: TObject; Index: Integer;var TabWidth: Integer) of object;

В качестве параметра Index передается индекс закладки в наборе. В ответ в параметре Tab Width обработчик должен вернуть потребную ширину для изоб­ражения этой закладки.

При этом высота пользовательских закладок устанавливается посредством свой­ства:

(Pb) property TabHeight: Integer;

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

После OnMeasureTab инициируется обработчик следующего события:

(Pb) property OnDrawTab: TDrawTabEvent;

TDr'awTabEvent = procedure (Sender: TObject; TabCanvas: TCanvas; R:

TRect; Index: Integer; Selected: Boolean) of object;

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

  • TabCanvas — канва компонента;
  • R — доступный для рисования прямоугольник;
  • Index — индекс закладки;
  • Selected — определяет, имеет ли эта закладка фокус.
У TTabSet есть собственная канва:
(Ro) property Canvas: TCanvas;

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

(Pb) property SelectedColor: TColor;

Цвет всех прочих закладок определяется свойством:

property UnselectedColor: TColor;

Фон, то есть оставшееся пространство до границ компонента, не принадлежа­щее закладкам, изображается цветом, заданным в свойстве:

(Pb) property BackgroundColor: TColor;

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

(pb) property DitherBackground: Boolean;

которое по умолчаншо установлено в True.


Компонент TTabbedNotebook

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCuscomControl -> TTabbedNoteBook

Модуль TABNOTBK

Страница Палитры компонентов Additional

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

(Pb) property TabsPerRow: Integer;
Как и TNotebook, этот компонент имеет свойства:
property ActivePage: string;
property Pagelndex: Integer;property Pages: TStrings;

Доступ к активной странице из набора Pages по-прежнему возможно двумя способами — через ActivePage и Pagelndex.

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

(Pb) property TabFont: TFont;

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

Найти индекс страницы с заданным именем позволяет метод

function GetlndexForPage(const PageName: string): Integer;

а установить фокус по номеру — метод:

procedure SetTabFocus(Index: Integer);

Щелчок на активной странице инициирует событие OnClick, а ее смена — OnChange:

(Pb) property OnChange: TPageChangeEvent;
TPageChangeEvent = procedure(Sender: TObject; NewTab: Integer; var AllowChange: Boolean) of object;

Параметры этого события идентичны TTabChangeEvent.


 

Группирование компонентов

По умолчанию родителем для большинства компонентов, размещенных на форме, является она сама. В ряде случаев, однако, есть необходимость отка­заться от этого правила, как визуально, так и функционально подчеркнув обособленность каких-то элементов управления. Для этого вы можете исполь­зовать специальные группирующие компоненты TGroupBox и TPanel. Мы также отнесли в эту группу компонент TScrollBox, он также обычно имеет дочерние компоненты, которые все вместе подвергаются прокрутке. Общим признаком для всех группирующих компонентов является наличие опции csAcceptsControls в свойстве ControlStyle.


 

Компонент TGroupBox

TObject -> TPersistent -> TCorr]ponent -> TControl -> TWinControl -> TCustomControl -> TCustomGroupBox -> TGroupBox

Модуль STDCTRLS

Страница Палитры компонентов Standard

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

Поэтому, для того чтобы на форме иметь несколько независимых групп радиокнопок, их нужно поместить на разные объекты типа TGroupBox. (Кстати, именно для решения задачи с радиокнопками есть специальный ком­понент — TRadioGroup).

Будучи потомком класса TCustomControl, TGroupBox наследует от него общие свойства, описанные ранее. Специфических свойств и методов этот компонент не имеет.


Компонент TPanel

TObject -> TPersistent -> TComponent -> TControl -> TWinControl ->  -> TCustomControl -> TCustomPanel -> TPanel

Модуль EXTCTRLS

Страница Палитры компонентов Standard

Этот компонент — панель — является несущей конструкцией для размещения других элементов управления. В отличие от простой рамки (TBevel) панель сама является оконным элементом управления и родителем для всех разме­щенных на ней компонентов. Часто ее используют для создания панелей инстру­ментов, строк состояния и т. п.

За внешнее оформление панели отвечают свойства:

(Pb) property Bevel Inner: TPanelBevel;
(Рb) property BevelOuter: TPanelBevel;
TPanelBevel = (bvNone, bvLowered, bvRaised);
(Pb) property BevelWidth: TBevelWidth;
TBevelWidth = 1..Maxint;
(Pb) property BorderWidth: TBorderWidth;
TBorderWidth = 0..Maxint ;

На границах панели размещаются две специальные окаймляющие рамки (bevels): Bevellnner и BevelOuter. При помощи комбинации белого и серого цветов они имитируют трехмерность — приподнятость (bvRaised) или утоп-ленность (bvLowered). Обе рамки имеют ширину BevelWidth. Наружная — BevelOuter — расположена прямо по периметру панели, вторая — Bevellnner — внутри на расстоянии BorderWidth от нее. Обе могут быть невидимыми (bvNone), приподнятыми или утопленными.

Комбинируя сочетания bvLowered/bvRaised, можно создать вокруг панели "ров" или "вал".

Иллюзию трехмерности может подчеркнуть также стиль обрамления компо­нента:

(Pb) property BorderStyle: TBorderStyle;
TBorderStyle = bsNone .. bsSingle;

Значение bsSingle означает, что панель будет окаймлена черной линией единичной толщины (по периметру, снаружи от обеих рамок).

Выравнивание текста заголовка панели определяется при помощи свойства:

(Pb) property Alignment: TAlignment;

Свойство(Pb)

property Locked: boolean;

предназначено для определения способа взаимодействия панели     с размещен­ными на ней объектами OLE. Если оно равно True, последние при      активизации сервера OLE "по месту'" не могут заместить панель. В обработчике события:

(Pb) property OnResize: TNotifyEvent; 

может быть предусмотрена реакция пользователя на изменение размеров панели.



Компонент TScrollBox

TObject -> TPersistent -> TCornponent -> TControl -> TWinControl -> . -> TScrollingWinControl -> TScrollBox

Модуль FORMS

Страница Палитры компонентов Additional

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

Указатели на горизонтальную и вертикальную полосы прокрутки являются свойствами компонента:

(Pb) property HorzScrollBar: TControlScrollBar;
(Рb) property VertScrollBar: TControlScrollBar;

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

Если свойство
(Pb) property AutoScroll: Boolean;

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

procedure ScrollInView(AControl: TControl);

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

Стиль обрамления компонента определяется свойством:

(Pb) property BorderStyle: TBorderStyle;

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

(Pb) property OnResize: TNotifyEvent; 

Рассмотрим свойства класса TControlScrollBar. Это полоса прокрутки, обяза­тельно принадлежащая какому-либо оконному элементу управления. Компо­нент этого типа не должен в явном виде создаваться пользователем, т. к. пара полос является составной частью компонента TScrollBox, а также формы TForm. Но зачастую бывает необходим доступ к свойствам полосы:

(Ro) property Kind: TScrollBarKind;
TScrollBarKind = (sbHorizontal, sbVertical);
Определяет направление полосы про­крутки.
(Pb) property Margin: Word;Определяет начальный отступ полосы прокрутки, который автоматически учитывается. По умолчанию его значение равно 0.
IPb) property Increment: TScrollBarInc; TScrollBarInc = 1..32767;Содержит минимальную единицу прира­щения при прокрутке.
(Pb) property Position: Integer;Содержит текущее положение бегунка. Это и следующее свойства изменяются системой, например, при перемещении бегунка, при смене фокуса у элементов и при изменении размеров содержащего полосу компонента.
(Pbi property Range: Integer;Определяет диапазон изменения положе­ния бегунка.
(Ro) property ScrollPos: Integer;Возвращает положение бегунка Position, если он видим. В противном случае свойство равно 0.

 

Компоненты — стандартные диалоговые окна Windows

В Windows, начиная с версии 3.1, появилась библиотека стандартных диало­говых окон COMMDLG.DLL, которая позволила заменить вызовом функций программирование рутинных операций в типовых случаях взаимодействия с пользователем. К этим случаям относятся выбор имени файла для чтения и записи, выбор цвета или шрифта, поиск и замена текста, настройка принтера и параметров печати. В Delphi предусмотрены компоненты, представляющие собой оболочку для этих стандартных диалогов.

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

  1. Настройка параметров диалога, во время которой устанавливаются те или иные возможности. У всех диалогов для этого предусмотрено свойство Options, но у некоторых есть и дополнительные свойства.
  2. Вызов метода Execute, который показывает диалоговое окно на экране и инициирует взаимодействие с пользователем. Execute является функцией:
  3. он возвращает True, если пользователь подтвердил ввод значения (т. е. нажал кнопку ОК на экране или клавишу <Enter> на клавиатуре) и False, если он отказался от выбора (т. е. нажал кнопку Cancel или клавишу <Esc>).
  4. В случае положительного ответа — чтение установленных значений в пред­ставляющем их свойстве (свойствах).
Примечание

Несколько отличается принцип взаимодействия в диалогах TFindDialog и TReplaceDialog, где нажатие кнопки подтверждения (Find и Replace соот­ветственно) инициирует событие, которое пользователь должен обработать.

По этой схеме и будет строиться описание компонентов. Естественно, метод Execute при этом опущен. Кроме того, общим для диалогов является свойство HelpContext. При нажатии кнопки Help вызывается система помощи именно с этим контекстом.



Компоненты TOpenDialog и TSaveDialog

TObject -> TPersistent -> TCoinponent -> TConimonDialog -> TOpenDialog -> TSaveDialog

Модуль DIALOGS

Страница Палитры компонентов Dialogs

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

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

(Рb) property Filter: string;

Формат строки фильтра состоит из двух частей. В первой задается крат­кое описание типа. Во второй части, которая отделяется символом '|' — маска поиска нужных файлов по расширению. В список файлов попадут толь­ко те, которые имеют указанные расширения. Примеры задания фильтра: 'Delphi projectsl*.dpr' или 'All   graphics files I *-bmp,*.ico,*.wmf '.

Таких пар строк для разных типов в фильтре может быть несколько, при этом форматы представления фильтра в самой системе Windows и в Delphi имеют одно отличие. При вызове стандартных диалогов Windows эти пары строк должны разделяться нулевым байтом, после последней строки также должен стоять нулевой байт. В рассматриваемых компонентах все строки раз­деляются символом 'Г.

Создавать строки вручную нужно лишь в редких случаях — для ввода значения свойства на этапе проектирования предназначен специальный редактор. Есть также простой способ составить фильтр для графических файлов — для этого предназначена процедура GraphicFilter (ее описание см. в разделе "Графическая подсистема").

В качестве начального фильтра при вызове диалога будет выбрана та пара строк, номер (индекс) которой совпадает со значением свойства:

(Pb) property Pilterlndex: Integer;

Если свойству не присваивалось значения, то по умолчанию выбирается первая пара.

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

(Pb) property InitialDir: string; 

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

(Pb) property DefaultExt: TFileExt;
TFileExt = string[3];

присваивается строка (до трех символов, без точки), которая и будет исполь­зоваться в качестве расширения по умолчанию. Например, если пользователь ввел в поле имени файла 'mybitmap', a DefaultExt равно 'bmp', то компонент вернет полное имя 'mybitmap. bmp'.

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

(Pb) property FileEditStyle: TFileEditStyle;
TFileEditStyle = (fsEdit, fsComboBox);

а содержимое списка ранее возвращавшихся имен — свойством:

(Pb) property HistoryList: TStrings; 

В случае действия стиля fsEdit это свойство не играет роли. Если же установ­лено fsComboBox, в выпадающем списке появляется содержимое HistoryList.

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

procedure TFormI-FileOpenClick(Sender: TObject);beginwith OpenDialogI do if Execute then beginMemol.Lines.LoadFromFile(FileName) ;HistoryList.Add(FileName);end;end;

У двух диалогов имеется большой набор опций. Часть из них является общей, часть — играет роль только для одного из диалогов:

(Pb) property Options: TOpenOptions;
TOpenOption = (ofReadOnly, ofOverwritePrompt, ofHideReadOnly, ofNoChangeDir, ofShowHelp, ofNoValidate, ofAllowMuItiSelect, ofExtensionDifferent, ofPathMustExist, ofFileMustExist, ofCreatePrompt, ofShareAware, ofNoReadOnlyReturn, ofNoTestFileCreate);
TOpenOptions = set of TOpenOption;

Три опции отвечают за работу с файлами со статусом "только для чтения":

  • ofReadOnly — делает флажок "Read only" помеченным при появлении;
  • ofHideReadOnly — прячет этот флажок в появляющемся диалоге;
  • ofNoReadOnlyRetum — запрещает выбор файлов "только для чтения", извещая о необходимости выбрать другой файл при нажатии ОК.

Также три опции ограничивают ввод имен для новых (несуществующих) фай­лов:

  • ofPathMustExist — указывает на то, что файл может находиться только в одном из существующих каталогов. В случае ввода несуществующего пути к файлу пользователь извещается об ошибке;
  • ofFileMustExist — аналогичньм образом указывает на то, что может быть выбран только один из существующих файлов;
  • ofCreatePrompt — опция устанавливает реакцию на предыдущую ситуацию. Если она установлена, то вместо сообщения об ошибке вьшодится запрос на создание нового файла.
Другие опции:
  • ofOverwritePrompt — запрашивает подгверждение, если пользователь вы­брал для записи уже существующий файл;
  • ofNoChangeDir — запрещает изменение начального каталога, с которьм диалог будет проинициализирован. Если она установлена, диалог каждый раз появляется с тем каталогом, который был установлен при первом запуске;
  • ofShowHelp — включает в состав диалога кнопку Help;
  • ofNo Validate — выключает проверку введенного имени файла на наличие в нем недопустимых символов;
  • ofAllowMultiSelect —позволяет выбирать несколько файлов одновременно;
  • ofShareAware — отключает проверку на возможность совместного доступа к выбранному файлу. В случае отстутствия этой опции файл нельзя вы­брать, если он открыт другим приложением;
  • ofNoTestFileCreate — эта опция применяется только для файлов на тех узлах локальной сети, которым разрешено создание, но не модификация файлов. Если она установлена, диалог не проверяет возможность записи на выбранном устройстве.

Наконец, одна опция — ofExtensionDifTereiit — является выходной. Она уста­навливается после завершения диалога в том случае, если расширение у вве­денного имени файла отличается от того, которое определено по умолчанию (в свойстве DefaultExt).

Текст, появляющийся в заголовке диалога, определяется свойством:

(Pb) property Title: string;

Если оно не было задано, то в заголовках диалогов появится "Open" для TOpenDialog и "SaveAs" для TSaveDialog.

В случае успешного завершения диалога в свойстве

(Ro) property Files: TStrings;

содержатся имена выбранных пользователем файлов. Если выбран один файл, его имя можно получить как Files.Strings[0], но есть для этого и отдельное свойство:

(Pb) property FileName: TFileName; 

Компонент TColorDialog

TObject -> TPersistent -> TCoinponent -> TCommonDialog -> TColorDialog
Модуль DIALOGS
 
Страница Палитры компонентов Dialogs

Предназначен для определения цвета пользователем. Настройка диалога осу­ществляется через свойство:

(Pb) property Options: TColorDialogOptions;
TColorDialogOption = (cdFullOpen, cdPreventFullOpen, cdShowHelp);
TColorDialogOptions = set of TColorDialogOption;
Данные опции определяют:
  • cdFullOpen — полный показ диалога. В этом случае пользователь может выбрать не только один из цветов системной палитры, но и задать соб­ственный;
  • cdPreventFullOpen — запрещение полного показа диалога;
  • cdShowHelp — показ кнопки Help.

В диалоге пользователь может определить несколько (до 16) собственных цве­тов, которые доступны в свойстве:

property CustomColors: TStrings;

Каждый из этих цветов представлен в свойстве CustomColors строкой вида

ColorA = SOffaO

где ColorA — условное название цвета (могут быть определены цвета с на­званиями от ColorA до ColorP), а справа от знака равенства стоит его шест­надцатиричное значение в формате RGB.

В случае нажатия кнопки ОК возвращаемое значение цвета содержится в свой­стве:

(Рb) property Color: TColor;

 

Компонент TFontDialog

TObject -> TPersistent -> TComponent -> TCommonDialog -> TFontDialog

Модуль DIALOGS

Страница Палитры компонентов Dialogs

Позволяет выбрать один из установленных в системе шрифтов.

В множество выбора могут быть включены шрифты, поддерживаемые только

принтером, дисплеем или обоими устройствами, что определяется в свойстве:

(pb) property Device: TFontDialogDevice;
TFontDialogDevice = (fdScreen, fdPrinter, fdBoth);

Диапазон возможных значений размеров (кеглей) шрифтов может быть ограничен с использованием свойств:

(Pb) property MinPontSize: Integer;(Pb) property MaxFontSize: Integer;

Ограничения действительны только при установленной опции fdLimitSizes (см. свойство Options). Если свойства установлены в 0, это означает, что соответ­ствующее ограничение отстутствует.

Опции диалогового окна определяются свойством:

(Pb) property Options: TFontDialogOptions;
TFontDialogOption = (fdAnsiOnly, fdTrueTypeOnly, fdEffects, fdFixedPitchOnly, fdForceFontExist, fdNoFaceSel, fdNoOEMFonts, fdNoSimulations, fdNoSizeSel, fdNoStyleSel, fdNoVectorFonts, fdShowHelp, fdWysiwyg, fdLirnitSize, fdScalableOnly);
TFontDialogOptions= set of TFontDialogOption;

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

  • fdAnsiOnly — включает только шрифты, содержащие стандартный набор символов Windows;
  • fdTrueTypeOnly — включает только шрифты TrueType;
  • fdScalableOnly — включает только масштабируемые шрифты;
  • fdFixedPitchOnly — включает только моноширинные шрифты;
  • fdWysiwyg — включает только шрифты, которые поддерживаются и диспле­ем, и принтером;
  • fdNoOEMFonts, fdNoVectorFonts — обе опции исключают из списка век­торные шрифты;
  • fdNoSimulations — исключает из списка те шрифты, которые моделируются графическим интерфейсом Windows;

В любом случае, выбрав шрифт, пользователь может установить его размер и стиль. Если задана опция fdEffects, в диалоге пользователь может определить дополнительные атрибуты: цвет шрифта и его подчеркивание (underline) и перечеркивание (strikeout).

Наличие опций fdNoFaceSel, fdNoSizeSel и fdNoStyleSel означает, что при инициализации диалога не будут заданы начальные значения шрифта, его размера и стиля соответственно.

Другие опции:
  • fdForceFontExist — включает возможность предупреждения пользователя о том, что он выбрал несуществующий тппиДт-
  • fdShowHelp — включает в состав диалога кнопку Help;
  • fdLimitSize — позволяет ограничивать размер выбираемого шрифта.

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

(Pb) property Font: TFont;

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

(Pb) property OnApply: TFDApplyEvent;
TFDApplyEvent = procedure(Sender: TObject; Wnd: HWND) of object;

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



Компонент TPrinterSetupDialog

TObject -> TPersistent -> TCornponent -> TCoiranonDialog -> TPrinterSetupDialog

Модуль DIALOGS

Страница Палитры компонентов Dialogs

Диалоговое окно установки параметров принтера. Оно поддерживается соот­ветствующим драйвером принтера и программисту никаких значений не воз­вращает, поэтому метод Execute у этого компонента — не функция, а про­цедура.


Компонент TPrintDlalog

TObject -> TPersistent -> TCornponent -> TCoinmonDialog -> TPrinterSetupDialog -> TPrintDialog

Модуль DIALOGS

Страница Палитры компонентов Dialogs

Предназначен для настройки параметров вывода текста на принтер. Опции этого диалога определяются свойством:

(pb) property Options: TPrintDialogOptions;
TPrintDialogOption = (poPrintToFile, poPageNums, poSelection, poWarning, poHelp, poDisablePrintToFile);
TPrintDialogOptions = set of TPrintDialogOption;
  • poWaming — извещает пользователя при инициализации диалога, если в системе нет установленных принтеров.
  • poHelp — включает в диалог кнопку Help;

Печать может быть перенаправлена в файл. Для этого в диалог может быть включен специальный флажок Print To File. Состояние его зависит от двух опций:

  • poPrintToFile — разрешает появление в диалоге этого флажка;
  • PoDisablePrintToFile — флажок показывается серьм цветом и переключение запрещено.По умолчанию для печати предназначается весь текст. Однако, если уста­новлены следующие опции, из него может быть напечатана только часть вместе с полями для ввода диапазона делается доступным);
  • poSelection — разрешает выбор только выделенного фрагмента текста (переключатель Selection делается доступным).

Остальные свойства компонента соответствуют разньм элементам управления диалога (кроме MinPage и MaxPage). Их начальные значения отображаются при вызове метода Execute.

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

property PrintRange: TPrintRange;
TPrintRange = (prAllPages, prSelection, prPageNums);
В случае prPageNums печататься будут страницы от определяемой свойством(Pb) property FromPage: Integer;до определяемой свойством(РЬ) property ToPage: Integer;

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

(Pb) property MinPage: Integer;fpB) property MaxPage: Integer;

Если пользователь ввел значение FromPage или ToPage, выходящее за пределы этого диапазона, то после нажатия кнопки ОК появится сообщение об ошибке, и диалог не будет завершен.

Если два последних свойства не определены (равны 0), то диапазоны и ограничения не действуют.

Если пользователь выбрал печать в файл, свойство

(Рb) property PrintToFile: Boolean;
будет равно True.

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

(Pb) property Copies: Integer;
Если свойство
(pd) property Collate: Boolean;

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


Компонент TFindDialog

TObject -> TPersistent -> TCornponent -> TCoiranonDialog -> TFindDialog 

Модуль DIALOGS

Страница Палитры компонентов Dialogs

С помощью этого диалога можно осуществить подготовку к поиску нужного фрагмента в тексте. В этом окне вы можете определить все нужные атрибуты, но написание собственно кода поиска все-таки возложено на программиста.

Рассмотрим опции, определенные в свойстве:

(pb) property Options: TFindOptions;
TFindOption= (frDown, frFindNext, frHideMatchCase, frHideWholeWord, frHideUpDown, frMatchCase, frDisableMatchCase, frDisableUpDown, frDisableWholeWord, frReplace, frReplaceAl1, frWholeWord, frShowHelp);
TFindOptions = set of TFindOption;

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

  • frDown — в случае наличия этой опции первоначальное направление поиска — вниз (от начала к концу). Устанавливается соответствующая радиокнопка;
  • frDisableUpDown — запрещает выбор направлений. Группа радиокнопок показывается серым цветом;
  • frHideUpDown — запрещает выбор направлений и прячет эту группу радиокнопок.

Поиск может осуществляться с учетом регистра символов. Если отмечен фла­жок Match Case, регистры символов должны совпадать, т. е. в этом случае "Word" не будет равно "word".

За состояние флажка отвечают следующие три опции:

  • frHideMatchCase — прячет флажок;
  • frDisableMatchCase — показывает флажок, но делает его неактивным. В обоих случаях учет регистра невозможен;

Если эти опции не установлены, флажок в диалоге активен, и его значение может быть изменено пользователем. Его значение соответствует наличию в Options опции frMatchCasc.

Также в диалоге предусмотрен флажок Match Whole Words Only, который разрешает или запрещает поиск заданного текста только в виде целых слов. Опции frHideWholeWord, frDisableWholeWord и frWholeWord имеют тот же смысл, что и три опции предыдущего флажка.

  • frShowHelp — включает в состав диалога кнопку Help;

Одна опция является информационной. Когда пользователь нажал кнопку Find Next, то опция frFindNext появляется в множестве Options.

При каждом случае, когда пользователь нажал кнопку Find Next, возникает событие:

(Рb) property OnFind: TNotifyEvent ;

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

(Pb) property FindText: string;

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

property Position: TPoint;
либо по отдельности:
property Left: Integer;
property Top: Integer;

Для вьшолнения рада оптаций программисту доступен дескриптор диалого­вого окна

(Ro) property Handle: HWnd;

и метод, закрывающий это окно:

procedure CloseDialog;

 

Компонент TReplaceDialog

TObject -> TPersistent -> TComponent -> TCominonDialog -> TFindDialog ->  -> TReplaceDialog

Модуль DIALOGS

Страница Палитры компонентов Dialogs

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

(Рb) property ReplaceText: string;

При нажатии кнопок Replace или Replace All в диалоге возникает событие

(Pb) property OnReplace: TNotifyEvent;

При этом в множество Options добавляется одна из новых опций — fi-Replace или frReplaceAll. В обработчике этого события нужно предусмотреть поиск и замену текста.

Использование стандартньк диалоговых окон иллюстрирует пример DEMOEDIT. Это простой однооконный редактор текста, который, однако, использует все семь компонентов-диалогов. Для поиска и замены в нем задействован модуль SEARCH, приведенный в одном из примеров фирмы Borland. Модуль можно найти в каталоге DELPHI\DEMOS\TEXTDEMO.


 

Типовые диалоги

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

Простейшую задачу — информирование пользователя сообщением — можно решить при помощи функций:

procedure ShowMessage(const Msg: string);
procedure ShowMessagePos(const Msg: string; X, Y: Integer);

В этом случае диалог состоит из статического текста Msg и кнопки ОК. Вторая функция отличается тем, что диалог можно поместить в требуемую точку (X.Y).

Когда после информирования пользователя требуется получить от него опре­деленный ответ, нужно применить одну из функций:

function MessageDig(const Msg: string; AType: TMsgDigType; AButtons:TMsgDigButtons; HelpCtx: Longint): Word;
function MessageDlgPos(const Msg: string; AType: TMsgDigType;AButtons: TMsgDigButtons; HelpCtx: Longint; X, Y: Integer): Word;

Здесь информация представлена в строке Msg и в пиктограмме, соответству­ющей типу диалога:

TMsgDigType = (mtWarning, mtError, mtlnformation, mtConfirmation, mtCustom);

В диалог можно включить любые кнопки из множества:

TMsgDIgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbignore, mbAll, mbHelp);
TMsgDigButtons = set of TMsgDIgBtn;

Для типовых случаев уже описаны подмножества кнопок:

mbYesNoCancel = [mbYes, mbNo, mbCancel];mbOKCancel = [mbOK, mbCancel];
mbAbortRetryIgnore = [mbAbort, mbRetry, mbignore] ;

Параметр HelpCtx указывает контекст системы помощи, который будет активизирован в случае нажатия <F1>.

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

Функция
function InputBox(const ACaption, APrompt, ADefault: string): string;

есть вызов диалога с заголовком ACaption, в котором подсказка APrompt приглашает набрать в редактирующем элементе текст. Первоначально в него загружается текст ADefault. Функция возвращает строку, находившуюся в редактирующем элементе на момент закрытия диалога.

Функция
function InputQuery(const ACaption, APrompt: string;var Value: string): Boolean;

выполняет аналогичные действия. Набранный текст будет содержаться в строке Value. Однако возвращает она булевское значение, в зависимости от того, нажал ли пользователь OK (<Enter>) или Cancel (<Esc>).

Наконец, если мало только получения ответа, и есть необходимость управлять диалогом во время его существования, воспользуйтесь функцией:

function CreateMessageDialog(const Msg: string; AType: TMsgDigType;AButtons: TMsgDigButtons): TPorm;

Она конструирует и возвращает указатель на форму, идентичную MessageDig с соответствующими параметрами.

Внешний вид последней группы диалогов можно изменить, переустановив зна­чения, определенные в модуле DIALOGS:

MsgDigButtonStyle: TButtonStyle = bsAutoDetect;
MsgDIgGlyphs: Boolean = True;

 

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

Зачастую возможностей стандартных диалогов (компоненты TOpenDialog и TSaveDialog) недостаточно для реалшации замыслов программиста. Во многих современных коммерческих приложениях перед открытием файла есть возмож­ность получить его характеристики и предварительно просмотреть содержимое. Чтобы дать разработчикам доступ к таким функциям, в библиотеку VCL были включены по отдельности и все составные части стандартного диалога — списки имен дисков, каталогов, файлов и фильтров расширений. Если уста­новить между ними взаимные ссылки, то они будут работать вместе, как в TOpenDialog, безо всякого дополнительного программирования. Вместе с тем, можно описать и специфическую реакцию на изменения этих списков.

Кроме того, в эту группу компонентов включен TDirectoryOutline — пример настройки компонента TOutline на конкретное приложение. Он отображает файловую структуру в виде дерева и также может работать в связке с осталь­ными компонентами этого раздела.



Компонент TDriveComboBox

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustornComboBox -> TDriveComboBox

Модуль FILECTRL

Страница Палитры компонентов System

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

TDriveType = (dtUnknown, dtNoDrive, dtFloppy, dtFixed, dtNetwork, dtCDROM, dtRAM);

К сожалению, функция, определяющая тип диска по его номеру или имени, недоступна программисту. Имеющаяся в API Windows функция GetDriveType не умеет распознавать dtCDROM и dtRAM и сообщает о них как о dtFixed.

Имя текущего диска соответствует значению свойства

property Drive: Char;

а имя с меткой (так, как это показывается в списке) — значению свойства:

property Text;

При этом текст метки может отображаться в верхнем или нижнем регистрах, в зависимости от значения свойства:

(Pb) property TextCase: TTextCase;TTextCase = (tcLowerCase, tcUpperCase);

Пиктограмму типа диска можно получить, используя свойство списка Items.Objects — каждому устройству соответствует объект типа TBitmap.

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

(Pb) property OnChange: TNotifyEvent;

нужно предусмотреть соответствующий код, например:

procedure TFormI.DriveComboBoxlChange(Sender: TObject);
begin
DirectoryListBoxl.Drive := DriveComboBoxl.Drive;
end;

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

(Pb) property DirList: TDirectoryListBox;

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


TDirectoryListBox

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomListBox -> TDirectoryListBox

Модуль FILECTRL

Страница Палитры компонентов System

Компонент представляет список каталогов на текущем устройстве. Устройство задается свойством

property Drive: Char;

а текущий каталог на нем — свойством:

property Directory: string;
При помощи метода
function GetIternPath(Index: Integer): string;

можно получить строку, содержащую полный путь к каталогу. Все символы в ней приводятся к верхнему регистру. Параметр Index означает номер каталога в списке (начиная с 0).

Если список каталогов связать со статическим текстом (меткой), пользуясь свойством

(Рb) property DirLabel: TLabel ;

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

Метод
procedure OpenCurcent ;

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

Наконец, обновление содержимого списка у этого    компонента     осуществляет метод:

procedure Update;

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

(Рb) property OnChange: TNotifyEvent;

или присвоив указатель на последний свойству:

(Рb) property FileList: TFileListBox;

В свойстве Items.Objects списка для каждого его элемента хранится объект типа TBitmap (пиктограмма, представляющая собой открытую или закрытую папку в зависимости от состояния каталога), доступный для чтения и записи.


Компонент TFileListBox

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomListBox -> TFlleListBox

Модуль FILECTRL

Страница Палитры компонентов System

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

property Drive: char;property Directory: string;

содержат имя устройства и каталога на нем, а метод

procedure Update;

обновляет список файлов. Метод

procedure AppiyFilePath (const EditText: string);

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

Свойство
(Рb) property FileEdit: TEdit;

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

property FileName: String;

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

(Pb) property FileType: TFileType;
TFileAttr = (ftReadOnly, ftHidden, ftSystem, fCVolumeID, ftDirectory, ftArchive, ftNormal);
TFileType = set of TFileAttr;

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

(Pb) property Mask: string;
Если свойство
(Pb) property MultiSelect: Boolean;

установлено в True, то в списке может быть одновременно выделено несколько файлов.

При смене текущего файла возникает событие:

property OnChange: TNotifyEvent;

Как и прежде, объекты Items.Objects в этом разделе представляют пиктограммы для разных типов файлов. Задает их показ значение True следующего свойства:

(Pb) property ShowGlyphs: Boolean; 

Компонент TFilterComboBox

TObject -> TPersistent -> TCoinponent -> TControl -> TWinControl -> TCustomComboBox -> TFilterComboBox

Модуль FILECTRL

Страница Палитры компонентов System

Этот компонент-комбинированный список предназначен для выбора шаблона-фильтра, который производит селекцию файлов по расширениям. Подробное описание синтаксиса такого шаблона см. в разделе "Компоненты-стандартные диалоговые окна Windows". Сам фильтр задается в свойстве:

(Pb) property Filter: string;

Он состоит из двух частей — описывающего тип текста и собственно шаблона. Они доступны и по отдельности через свойства:

(Ro) property Mask: string;
property Text: string;

В компоненте должна быть определена ссылка на список файлов, где будут отражаться изменения фильтра. Он должен иметь тип TFileListBox, что опре­деляется свойством:

(Pb) property FileList: TFileListBox;

При изменении текущего элемента списка возникает событие:

property OnChange: TNotifyEvent;

 

Компонент TDirectoryOutline

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustomControl -> CustomGrid -> TCustomOutline -> TDirectoryOutline

Модуль DIROUTLN

Страница Палитры компонентов Samples

Этот компонент создан для отображения иерархического дерева файлов и каталогов текущего диска и, таким образом, может заменить сразу компонен­ты TDirectoryListBox и TFileListBox. Он имеет много общего с компонентом TOutline, отличие заключается в возможности работы только с файловой струк­турой.

Значения текущего диска, содержимое файловой системы которого отобража­ется в дереве, устанавливается посредством свойства:

property Drive: Char;

Текущий каталог соответствует значению свойства:

property Directory: TFileName;

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

Стиль отображаемых имен файлов и каталогов определяет свойство:

(Рb) property TextCase: TTextCase;
TTextCase = (tcLowerCase, tcUpperCase, tcAsIs) ;
  • tcLowerCase — преобразование к нижнему регистру;
  • tcUpperCase — преобразование к верхнему регистру;
  • tcAsIs — без преобразования.
Метод
function ForceCase(const AString: string): string;

может использоваться для пребразования строки, передаваемой в параметре AString, в соответствии с текущим стилем свойства TTextCase.


Таймер

TObject -> TPersistent -> TCoinponent -> TTimer

Модуль EXTCTRLS

Страница Палитры компонентов System

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

Свойство
(Pb) property Enabled: Boolean;

включает/выключает таймер, влияя на генерацию им событий. Будучи уста­новлен в Enabled, таймер начинает генерировать события OnTimer через интер­вал времени

(Рb) property Interval: Word;

который измеряется в миллисекундах. После каждого истечения такого интер­вала инициируется обработчик, связанный с событием:

(Pb) property OnTimer: TNotifyEvent;

При этом программист получает очередной квант времени.

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



Работа со средствами мультимедиа

TObject -> TPersistent -> TComponent -> TControl -> TWinControl -> TCustoinControl -> TMediaPlayer

Модуль MPLAYER

Страница Палитры компонентов System

Для управления устройствами мультимедиа в Windows предназначен интерфейс MCI (Media Control Interface). С каждым из таких устройств, как правило, поставляется специальный драйвер, который должен поддерживать некоторое подмножество определенных в MCI управляющих и информационных команд. Подробным образом интерфейс MCI рассмотрен в [З].

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

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

(Pb) property DeviceType: TMPDeviceTypes;
TMPDeviceTypes = (dtAutoSelect, dtAVIVideo, dtCDAudio, dtDAT, dtDigitalVideo, dtMMMovie, dtOther, dtOverlay, dtScanner, dtSequencer, dtVCR, dtVideodisc, dtWaveAudio);

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

Набор возможностей устройства определяется свойством:

(Ro) property Capabilities: TMPDevCapsSet;
TMPDevCaps = (mpCanStep, mpCanEject, rripCanPlay, mpCanRecord, mpUsesWindow);
TMPDevCapsSet = set of TMPDevCaps;
  • mpCanStep — устройство имеет пошаговый режим;
  • mpCanEject — имеет возможность извлечения носителя;
  • mpCanPlay — имеет режим воспроизведения;
  • mpCanRecord — имеет режим записи;
  • mpUsesWindow — устанавливается для устройств вывода видео, использу­ющих окно.

В таблице приведены методы и свойства, обеспечивающие выполнение основ­ных команд интерфейса MCI:

procedure Open;Производит открытие устройства. Если свойство AutoOpen установлено в True, открытие осуществляется автоматически при создании объекта типа TMediaPlayer. Большинство остальных методов могут ра­ботать только с открытым устройством, так как используют полученный при открытии идентификатор DeviceID. Их вызов при неоткрытом устройстве приводит к генерации исключительной ситуации EMCIDeviceError. Если объект перед этим был связан с открытым устройством MCI, оно при этом закрывается.
  Производит закрытие устройства.
procedure Play;Включает режим воспроизведения (для устройств, имеющих опцию mpCanPlay в свойстве Capabilites).
procedure StartRecording;Включает режим записи (для устройств, имеющих опцию mpCanRecord в свойстве Capabilites).
property StartPos: Longint; property EndPos: Longint;Предназначены только для работы с методами Play и StartRecording. Определяют начало и конец фрагмента, который необходимо воспроизвести (или записать). После каждой операции (Play/StartRecording) свойства сбрасываются, и их нужно переустанавливать. Могут применяться как в паре, так и по отдельности. При установке этих свойств свойство Position не изменяется вплоть до начала операции. Если свойства не устанавливались, то воспроизведение и запись начинаются с текущей позиции данных (см. свойство Position).
(Pb) property AutoRewind: Boolean; procedure Rewind;Если перед воспроизведением носитель данных находится в крайнем положении (и при этом не используются свойства StartPos и EndPos), то при свойстве AutoRewind, равном True, перед началом проводится перемотка в начальное положение (Rewind).
procedure Stop;Останавливает работу в режиме воспроиз­ведения или записи.
procedure Pause; procedure PauseOnly; procedure Resume;Три метода предназначены для временной остановки (Pause, PauseOnly) и возобновле­ния (Resume) работы в режимах воспроиз­ведения/записи. Отличие Pause от PauseOnly в том, что происходит при втором вызове метода: если повторно вызвать Pause, то останов снимается (вызывается Resume), a если устройство остановлено посредством PauseOnly, то Resume нужно вызывать самому.
procedure Step; procedure Back;Перемещают позицию данных вперед/назад на число кадров, равное значению свойства Frames (см. ниже). Методы имеют смысл только для устройств, поддерживающих покадровый режим (пока это только устройства видео).
procedure Next; procedure Previous;Если данные на устройстве имеют дорожки, то эти методы перемещают текущую их пози­цию к началу следующей (предыдущей) до­рожки. При вызове Next на последней дорож­ке или при вызове Previous на первой — до­рожка не меняется, происходит позициони­рование к ее началу. Для устройств, не имею­щих разбивки на дорожки, происходит пере­мещение к началу (концу) данных соответ­ственно.
procedure Eject;Извлекает носитель данных из устройства (например, компакт-диск). Действителен только для устройств с опцией mpCanEject).
procedure Save;Для тех устройств, которые хранят инфор­мацию в файлах, сохраняет ее в файле с именем, содержащимся в свойстве FileName.
 
Каждая операция MCI возвращает код завершения. В случае необходимости проверки программист может получить и проанализировать его, используя два свойства:
 
(Ro) property Error: Longint;Код ошибки, возвращаемый функцией MCI.
(Ro) property ErrorMessage: string;Соответствующая этому коду строка-сообщение об ошибке. Если ее невозможно получить от драйвера MCI, возвращается сообщение о неизвестной ошибке.

Пользуясь свойством Mode, можно узнать текущее состояние устройства. Смысл режимов ясен из названий соответствующих констант:

(Ro) property Mode: TMPModes;
TMPModes = (mpNotReady, mpStopped, mpPlaying, mpRecording, mpSeeking, mpPaused, mpOpen);

Следующие свойства дают информацию о характеристиках и состоянии ус­тройства:

(Ro) property Start: Longint;

— начальная позиция данных (если имеются дорожки — позиция первой до­рожки);

(Ro) property Length: Longint;

— длина данных;

(Ro) property Position: Longint;

— текущая позиция данных относительно начала (если имеются дорожки — относительно начала текущей дорожки).

Эти три свойства зависят от носителя данных (например, от вставленного компакт-диска или загруженного файла AVI). Значение свойств, хотя и имеет тип Longint, представлено и должно интерпретироваться в зависимости от формата представления времени (свойство TimeFormat).

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

(Pb) property Tracks: Longint;
— число дорожек;
(Pb) property TrackLength[TrackNum: Integer]: Longint;
— длина дорожки с номером TrackNum. По умолчанию используется формат времени tfMSF (см. ниже);
(Pb) property TrackPosition[TrackNum: Integer]: Longint;
— начальное положение заданной дорожки.

Число кадров, на которое перемещается позиция устройства при шаге впе­ред/назад (операциях Step/Back), определяется свойством:

property Frames: Longint;
По умолчанию оно равно Length/10. Свойство
property Wait: Boolean;

устанавливает состояние ожидания окончания операции. Если оно установлено в True, функции MCI (Open, Play и т. п.) вернут управление только по за­вершении операции. В противном случае отследить конец операции можно, используя свойство:

property Notify: Boolean;

Если это свойство установлено в True, драйвер MCI посылает медиаплейеру специальные извещения о завершении каждой операции. Результат операции присваивается свойству:

(Ro) property NotifyValue: TMPNotifyValues;
TMPNotifyValues = (nvSuccessful, nvSuperseded, nvAborted, nvFailure);
  • nvSuccessful — успешное окончание;
  • nvSuperseded — устройство получило еще одну команду, требующую изве­щения, и извещение от данной операции не будет получено;
  • nvAborted — операция прервана;
  • nvFailure — ошибка во время выполнения операции;

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

(Pb) property OnNotify: TNotifyEvent;

Если программист хочет использовать свойства Wait и Notify, он должен устанавливать их значения специально перед каждой операцией MCI. После ее завершения их значения более не актуальны и не принимаются во внимание, пока снова не будут переустановлены. Когда свойства не действуют, устройство ожидает конца операции и не посылает извещений (как если бы Wait=True и Notify = False).

Идентификатор устройства, получаемый им при открытии (вызове метода Open), равен значению свойства:

(Ro) property DeviceID: Word;

Он необходим, когда программист хочет сам вызвать функцию API mciSendCommand для выполнения действий, не предусмотренных методами данного класса. В качестве примера приведена функция, позволяющая уз­нать наличие носителя данных в устройстве (такая возможность в компоненте TMediaPlayer, к сожалению, отсутствует):

function TForm1.MediaPresent: boolean;
var
    StatusParm: TMCI_Status_Parms;
begin
    StatusParm.dwItem := mci_Status_Media_Present;
    inciSendCoimnand(MediaPlayerl.DeviceID, mci_Status, nici_Wait or mci_Status_Itein, Longint (QStatusParm));
    Result := StatusParm.dwReturn;
end;

Перейдем к рассмотрению единиц измерения интервалов и форматам их пред­ставления. Их устанавливает свойство:

property TimeFormat: TMPTimeForinats;
TMPTirneFormats = (tfMilliseconds, tfHMS, tfMSF, tfFrames, tfSMPTE24, tfSMPTE25, tfSMPTE30, tfSMPTE30Drop, tfBytes, tfSamples, tfTMSF);
Такие свойства, как Length, Position и другие возвращают значения типа Longint. В зависимости от TimeFormat они могут быть проинтерпретированы как:
  • tfMilliseconds — число миллисекунд;
  • tfHMS — младший байт: часы/минуты/секунды. Старший байт не задей­ствован;
  • tfMSF — младший байт: минуты/секунды/кадры. Старший байт не задей­ствован;
  • tfFrames — число кадров;
  • tfSMPTE24, tfSMPTE25, tfSMPTE30, tfSMPTE30Drop — младший байт: часы/минуты/секунды/кадры. Числа 24, 25 и 30 означают число кадров в секунду;
  • tfBytes — число байт;
  • tfSamples — число отсчетов;
  • tfTMSF — младший байт: дорожки/минуты/секунды/кадры.

Для кодирования и декодирования информации в этих форматах используйте модуль MMSystem, где предусмотрены соответствующие функции. Для ус­тройств, имеющих дорожки (типов dtCDAudio и dtVideoDisc), в конструкторе устанавливается формат tfTMSF.

Два свойства предназначены специально для устройств видео (таких, как dtAVIVideo, dtDigitalVideo, dtOverlay, dtVCR, dtVideodisc). Первое из них

(Pb) property Display: TWinControl;

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

property DisplayRect: TRect;

Если значение свойства не определено, вывод в область не производится.

Уже говорилось о том, что для пользователя компонент TMediaPlayer выглядит как набор кнопок, каждая из которых соответствует команде MCJ. Все типы кнопок определены в множестве:

TMPBtnType = (btPlay, btPause, btStop, btNext, bCPrev, btStep, btBack, btRecord, btEject);
TButtonSet = set of TMPBtnType;

Отображением кнопок в составе TMediaPlayer во время выполнения управляют три свойства:

(Pb) property VisibleButtons: TButtonSet;

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

if not (rnpCanRecord in Capabilities) then VisibleButtons := VisibleButtons-[btRecord];
Свойство
(Pb) property ColoredButtons: TButtonSet;

определяет цветовую раскраску кнопок. Каждой операции (как это принято, например, в бытовой технике) соответствует свой цвет. Значок операции на кнопках, попавших в это множество, в случае их видимости также будет цветным. По умолчанию все кнопки имеют это свойство. Следующее свойство

(Pb) property EnabledButtons: TButtonSet;

определяет множество разрешенных кнопок. Оно должно изменяться в зависимости от выполняемой операции (например, при нажатии Pause запре­щается и Stop). Объект сам может управлять состоянием своих кнопок, если его свойство:

(Pb) property AutoEnable: Boolean;
установлено в True. Еще три опубликованных свойства:
(Pb) property AutoOpen: Boolean;

— если это свойство установлено в True, устройство автоматически открыва­ется сразу после загрузки TMediaPlayer;

(Pb) property FileName: string;

— имя файла. Используется в том случае, если данные мультимедиа хранятся в файле (например, для dtAVIVideo и dtWaveAudio);

(Pb) property Shareable: Boolean;

— используется при открытии устройства. True означает возможность однов­ременного открытия его другими задачами (другими объектами TMediaPlayer).

Пара событий, возникающих при нажатии кнопок TMediaPlayer определяется свойствами:

(Pb) property OnClick: EMPNotify;
EMPNotify = procedure (Sender: TObject; Button: TMPBtnType; var DoDefault: Boolean) of object;
(Pb) property OnPostClick: EMPPostNotify;
EMPPostNotify = procedure (Sender: TObject; Button: TMPBtnType) of object;

Обработчику события OnClick передается тип нажатой кнопки в параметре Button. В результате обработки он должен вернуть значение в параметре DoDefault. Если оно равно True, вызывается соответствующая кнопке функция MCI и после этого — OnPostClick. Если оно равно False, ничего не происходит (подразумевается, что пользователь сам вызвал требуемые функции MCI).

Для того чтобы проиллюстрировать работу компонента TMediaPlayer, на прилагаемой к книге дискете имеется пример использования проигрывателя CD-аудиодисков CDPLAYER. В нем реализованы все команды управления проигрывателем и отображается его текущее состояние в компоненте-индика­торе типа TGauge.


Динамический обмен данными (DDE)

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

Приложения, использующие DDE, разделяются на две категории — клиенты и серверы (не путать с одноименной архитектурой СУБД). Оба участника процесса осуществляют контакты (conversations) по определенным темам (topic), при этом в рамках темы производится обмен элементами данных (items). Устанавливает контакт клиент, который посылает запрос, содержащий имена контакта и темы. После установления контакта всякое изменение элемента данных на сервере передается данным клиента. Подробно функции DDE описаны в [4].

Первоначально программирование DDE было чрезвычайно сложным делом — оно требовало взаимосвязанной обработки более чем десяти сообщений Win­dows. В версии Windows 3.1 появилась библиотека DDEML, которая перевела управление DDE на уровень вызова процедур. Разработчики подсистемы DDE в Delphi, верные идеологии создания VCL, свели интерфейс этого протокола к четырем компонентам — двум для сервера и двум для клиента.

На уровне поддержания контакта лежат компоненты TDDEServerConv и TDDEClientConv. Первый играет пассивную роль — он только указывает имя одной из поддерживаемых сервером тем. Все операции по установлению и разрыву контакта осуществляет из приложения-клиента второй компонент.

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

TDDEServerItem и TDDEClientItem. Каждый из них во время работы должен указывать на контакт, к которому он привязан. Кроме того, в составе обоих есть свойства, содержащие некий текст. При установленном контакте их со­держимое синхронизируется.

Помимо этого в модуле DDEMAN описан и пятый компонент, который уп­равляет всеми связями DDE. Его рассмотрение выходит за рамки книги.

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


Компонент TDDeServerConv

TObject -> TPersistent -> TCoinponent -> TDDeServerConv

Модуль DDEMAN

Страница Палитры компонентов System

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

В моменты открытия и закрытия контакта возникают события:

(ph) property OnOpen: TNotifyEvent;
(РЕ) property OnClose: TNotifyEvent;

Первоначально протокол DDE был ориентирован только на оперативное полу­чение данных клиентом от сервера, но позже его возможности расширились. Клиент может передать для выполнения серверу набор макрокоманд — для этого у него есть нужные методы. На стороне сервера за их исполнение отвечает обработчик события:

(pb) property OnExecuteMacro: TMacroEvent;
TMacroEvent= procedure(Sender: TObject; Msg: TStrings) of object;

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

function ExecuteMacro(Data: HDDeData): Longint;

В этом случае параметр Data должен содержать дескриптор строки с командами (типа pChar).


Компонент TDDeServerltem

TObject -> TPersistent -> TComponent -> TDDeServerItern

Модуль DDEMAN

Страница Палитры компонентов System

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

только текстовыми данными. Так что свойство, содержащее формат обмена данными,

property Fmt: Integer; 
всегда равно CF_TEXT. Данные содержатся в свойствах:
property Text: string;
property Lines: TStrings;

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

(Pb) property ServerConv: TDDeServerConv; 

может быть задана ссылка на компонент типа TDDEServerConv, чье имя будет темой контакта DDE. Можно обойтись и без использования такого компо­нента. В этом случае именем темы будет являться заголовок (Caption) той формы, которая содержит TDDEServerItem. Элемент данных может быть скопирован в буфер обмена в специальном фор­мате (в виде информации о контакте), с помощью метода:

procedure CopyToClipboard;

Для вступления в контакт посредством буфера обмена клиент может вызвать функцию GetPasteLinkInfo (см. ниже), и, проанализировав имена сервера, темы и элемента, принять решение о вступлении. Клиент может переустановить данные сервера. При переустановке возникает событие:

(Pb) property OnPokeData: TNotifyEvent;

Кроме того, для этого вами может быть использован метод:

function PokeData(Data: HDDeData): Longint;

Параметр Data должен представлять собой дескриптор области памяти, в которой содержится текстовая строка типа pChar. В отличие от OnPokeData, событие:

(Pb) property OnChange: TNotifyEvent;

возникает при любом изменении данных, как при присвоении значений свой­ствам Text или Lines, так и при вызове PokeData. Оно может также быть вызвано явно из метода:

procedure Change;

 

Компонент TDDECIIentConv

TObject -> TPersistent -> TComponent -> TDDEClientConv

Модуль DDEMAN

Страница Палитры компонентов System

Компонент TDDEClientConv осуществляет контакт на клиентской стороне. Именно в нем описаны методы, отвечающие за установление контакта. Имена требуемых сервера DDE и темы содержатся в свойствах:

property DDEService: String;
property DDETopic: String;

Сервер и тема устанавливаются при вхождении в контакт. Предусмотрены два режима вхождения в него:

(Pb) property ConnectMode: TDataMode;
TDataMode= (ddeAutomatic, ddeManual);
Метод
function SetLink(const Service: string; const Topic: string): Boolean;

присваивает серверу и теме имена, равные Service и Topic, а если выбран режим контакта ddeAutomatic — то и устанавливает контакт. Будьте внима­тельны при задании параметров метода— здесь учитывается регистр символов. В случае режима ddeManual для установления контакта необходимо вызвать дополнительно метод:

function OpenLink: Boolean;

Этот метод сначала закрывает предыдущий контакт, затем он пытается свя­заться с сервером DDEService на тему DDETopic. Если это не удается сразу (например, если требуемый сервер DDE отсутствует), то делается попытка загрузить программу с именем, определенным в свойстве

(Pb) property ServiceApplication: String;

и установить контакт с ней. Если оно не определено (ServiceApplication = "), то в качестве последней попытки для контакта пробуется имя, представляющее собой конкатенацию имен сервера и темы, разделенных пробелом. В случае неудачи метод OpenLink возвращает False.

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

function PasteLink: Boolean;

переключит компонент на новый контакт и вернет значение True. Наконец, метод

procedure CloseLink;разрывает контакт с сервером DDE. Метод
function StartAdvise: Boolean;

инициирует начало обмена данными. Обычно он вызывается в методе OpenLink.

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

function PokeDataLines(const Item: string; Data: TStrings): Boolean;
function PokeData(const Item: string; Data: PChar): Boolean;

Здесь Item — имя элемента данных, Data — передаваемые текстовые данные. Кроме того, некоторые серверы DDE имеют собственные наборы макрокоманд, запрос на выполнение которых можно послать от клиента. К ним относятся многие приложения, в т. ч. СУБД и электронные таблицы, такие, как Paradox и MS Excel; наиболее типичным примером служит Program Manager. Запрос на выполнение макрокоманд посылают методы:

function ExecuteMacroLines(Cmd: TStrings; waitFIg: Boolean): Boolean;
function ExecuteMacro(Cmd: PChar; waitFIg: Boolean): Boolean;

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

(Ro) property WaitStat: Boolean;

устанавливается в True. При этом вызовы последних четырех описанных ме­тодов отрабатываться не будут, пока сервер не известит об окончании опе­рации, и WaitStat не примет значение False. Это свойство доступно только по чтению. Клиент может запросить данные от сервера немедленно с помощью метода:

function RequestData(const Item: string): PChar;

Формат обмена данными можно узнать из свойства:

(Ro) property DDEPmt: Integer;

Перефразируя Генри Форда, скажем, что можно обмениваться данными любого формата, если этот формат — CF_TEXT.

Если возможностей, предоставляемых методами и свойствами класса, недоста­точно, то для вызова процедур библиотеки DDEML программисту доступен дескриптор контакта:

(Ro) property Conv: HConv;

В полученном от сервера тексте могут быть специальные управляющие символы — <Enter>, <Tab>, <Backspace> и другие. Их можно отфильтровать (подавить), если свойство

(Pb) property FormatChars: Boolean;

установлено в False. В этом случае все символы ASCII с десятичными кодами от 1 до 31 заменяются на пробел (код 32). В случае True преобразования не происходит.

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

(pk) property OnOpen: TNotifyEvent;
(Pb) property OnClose: TNotifyEvent;
Свойство
property DataMode: TDataMode;

по-видимому, зарезервировано ддя дальнейших применений.


Компонент TDDECIientltem

TObject -> TPersistent -> TComponent -> TDDEClientItem

Модуль DDEMAN

Страница Палитры компонентов System

Этот компонент представляет элемент данных на клиентской стороне. После установления контакта с сервером нужно присвоить свойству

(Pb) property DDEConv: TDDEClientConv;

указатель на объект, соответствующий появившемуся контакту, а свойству

(Pb) property DDEItem: String;

имя элемента данных сервера. В этом случае все изменения будут отслеживаться.

В рассмотренном ниже примере приложение-клиент вступает в контакт с сер­вером InfbServer на тему TimeTopic. При нажатии кнопки TimeButton связь устанавливается, при отпускании — разрывается. Метод TimeConvOpen, слу­жащий обработчиком события ОпОреп, присваивает значения именам темы и элемента данных.

constInfoServer = 'infoserv';
TimeConversation = 'TimeTopic';
ServerTimeItem = 'Timeltem';
SCannotStart = 'Cannot start conversation';

procedure TFormI.TimeButtonClick(Sender: Tobject);
begin
    if TimeButton.Down then
    begin
        if not TimeConv.SetLink(InfoServer, TimeConversation) or not TimeConv.OpenLink then
        begin
            MessageDIg(SCannotStart, mtError, [mbOk], 0);
            TimeButton.Down := False;
        end
    end
    else
        TimeConv.CloseLink;
end;

procedure TPormI.TimeConvOpen(Sender: TObject);
begin
    ClientTimeItem.DDEConv := TimeConv;
    ClientTimeItem.DDEItem := ServerTimeItem;
end;

Организация данных у клиента сходна с той, которая принята на сервере:

(Pb) property Text: String;
(Pb) property Lines: TStrings;
Свойство Text является подмножеством Lines и содержит первую строку этого набора.

Когда изменяются данные на сервере, эти изменения отражаются в TDDEClientItem. В этот момент происходит событие:

(Pb) property OnChange: TNotifyEvent;

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

Принципы работы с DDE отражены в примере DDEINFO. Приложение-сервер запускает таймер и с установленным периодом формирует текстовые строки со значением текущего времени и количества свободной памяти. Эти строки являются элементами данных соответствующих тем DDE. На форме клиента находятся две кнопки — Time и Memory. При их нажатии происходит попытка входа в соответствующий контакт. Если она была успешной, кнопка утаплива­ется, и на ней отображается время или количество свободной памяти. При отжатии кнопки контакт разрывается.


Дополнительные компоненты

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


Компонент TGauge

TObject -> TPersistent -> TCoinponent -> TControl -> TGraphicControl -> TGauge

Модуль GAUGES

Страница Палитры компонентов Samples

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

Стиль компонента задается свойством

(pb) property Kind: TGaugeKind;
TGaugeKind= (gkText, gkHorizontalBar, gkVerticalBar, gkPie, gkNeedle);
  • gkText — текстовый вывод величины в процентах;
  • gkHorizontalBar — горизонтальное заполнение;
  • gkVerticalBar — вертикальное заполнение;
  • gkPie — отклонение "стрелки спидометра";
  • gkNeedle — заполнение сектора окружности.

Остальные свойства приведены в таблице:

(Pb) property Color;Определяет цвет панели компонента. Играет роль только при стилях gkPie, gkNeedle.
(Pb) property ForeColor: TColor;Определяет цвет указателя текущего значения.
(Pb) property BackColor: TColor;Определяет цвет указателя фона.
(Pb) property MinValue: Longint;Определяет минимальное значение шкалы измерения.
(pb) property MaxValue: Longint;Определяет максимальное значение шкалы измерения.
(Pb) property Progress: Longint;Определяет абсолютное текущее значение индикатора.
(Ro) property PercentDone: Longint ;Содержит значение в процентах (по отноше­нию к MaxValue).
(Pb) property ShowText: Boolean;Задает видимость цифр текущего значения на табло индикатора.
Procedure AddProgress(Value:Используется для динамического изменения текущего значения. Value — добавляемое значение.

 

Компонент TCalendar

TObject -> TPersistent _. TComponent -> TControl -> TWinControl -> TCustomControl -> TCustomGr id -> ТСаlendar
Модуль CALENDAR
 
Страница Палитры компонентов Samples

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

property Year: Integer;
property Month: Integer;
property Day: Integer;

Внешний вид его определяется свойствами:

(Pb) property GridLineWidth;

— толщина разграничивающих линий;

property Color;
— цвет панели компонента.

День, с которого начинается отображение недели, определяется свойством:

(Pb) property StartOfWeek: TDayOfWeek;
TDayOfWeek = 0..6 ;