18.2. КОМПОНЕНТЫ СТРАНИЦЫ ADDITIONAL

18.2.1. TBitBtn - кнопка с изображением

Пиктографическая кнопка TBitBtn представляет собой популярную разновидность стандартной кнопки TButton. Ее отличительная особенность - свойство Glyph, с помощью которого определяется растровое изображение, рисуемое на поверхности кнопки. В состав поставки Delphi входит множество рисунков, разработанных специально для размещения в этих кнопках (по умолчанию для старших версий Delphi эти рисунки размещаются в папке program Files |

Common Files | Borland Shared | Images | Buttons, для остальных версий - в папке images l Buttons каталога размещения Delphi).

Свойство Kind определяет одну из 11 стандартных разновидностей кнопки, показанных на рис. 18.9.

Рис. 18.9. Разновидности кнопок TBitBtn

Нажатие любой из них, кроме bkCustom и bkHelp, закрывает модальное окно и возвращает в программу результат mrxxx: bkok - mrОk, bkCancel - mrCancel И Т. Д. Кнопка bkClose для модального окна возвращает mrCancel, а для главного окна программы - закрывает его и завершает работу программы. Кнопка bkHelp автоматически вызывает раздел справочной службы, связанный с Heipcontext формы, на которую она помещена. Если у кнопки была изменена пиктограмма Glyph, Delphi автоматически присвоит ей Kind=bkCustom. Это произойдет также в случае, когда кнопка указана как умалчиваемая (Defauit=True), но Kind не содержит bkok или bkYes, а также если ее свойство Cancel содержит True, a Kind нe содержит bkCancel или bkNo.

Свойства Cancel, Default И ModalResult кнопка TBitBtn унасле-довала у своего родительского класса TButton, остальные специфичные свойства указаны ниже:

property Glyph: TBitmap; TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose, bkAbort, bkRetry, bklg-nore, bkAll) ; property Kind: TBitBtnKind; | Определяет от 1 до 4 связанных с кнопкой растровых изображения (см. ниже) Определяет разновидность кнопки (рис. 18.9)
TButtonLayout = (bIGlyphLeft, bIGlyphRight, bIGlyphTop, bIGlyphBottom) ; property Layout: TButtonLayout; | Определяет край кнопки, к которому прижимается пиктограмма: bIGlyphLeft - к левому; bIGlyphRight - к правому; bIGlyphTop - к верхнему;biGlyphBottom - к нижнему)
property Margin: Integer; | Определяет расстояние в пикселях от края кнопки до пиктограммы
TNumGlyphs: 1..4 ; property NumGlyphs: TNumGlyphs; | Определяет количество растровых изображений (см.ниже)
property Spacing: Integer; | Определяет расстояние в пикселях от пиктограммы до надписи на кнопке
TByttonStyle = (bsAutoDetect, bsWinSI, bsNew) ; property Style: TButtonStyle; | Определяет стиль оформления кнопки, зависящий от операционной системы. Стиль bsNew соответствует 32-разрядным версиям Windows. Стиль bsAutoDetect изменяет оформление кнопки в зависимости от ОС, под управлением которой работает программа в данный момент

Примечание

> При разработке собственных растровых изображений для использования в кнопках следует учесть, что изображения должны меняться? при изменении состояния кнопки. Таких состояний может быть четыре: нормальное, запрещенное, нажатое и утопленное (последнее используется только в кнопках TSpeedButton). В соответствии с этим! разрабатывается до 4 пиктограмм, расположенных по горизонтали ввиде одного длинного растра. Например, стандартный размер пиктограммы для размещения на кнопке равен 16х16 пикселей. Если создаются 3 пиктограммы, размер растра должен составлять 48х16. Количество пиктограмм в растре задается свойством NumGlyphs. Если каждая; пиктограмма - квадратная и длина растра делится без остатка; на его высоту, Delphi автоматически распознает количество пиктограмм. Если задана только одна пиктограмма, ее изображение, меняется автоматически: в состоянии “нажатая” пиктограмма смещается! на один пиксель вправо и, вниз, а в состоянии “запрещенная” все цвета, кроме черного, меняются на светло-серый, а черный на белый, что обеспечивает эффект "вдавленности" изображения. Следует так же учесть, что самый левый нижний пиксель растра определяет цвет прозрачности: на кнопке этот цвет будет заменяться цветом поверхности кнопки.

Как и в кнопках TButton, программист не может управлять цветом поверхности кнопки, но в отличие от TButton может менять цвет надписи на ней. С помощью свойства Default кнопку можно сделать умалчиваемой - в этом случае нажатие Enter автоматически вызывает обработчик ее события OnClick. Однако умалчиваемыми можно сделать только кнопки bkYes и bkNo, остальные значения свойства Kind будут заменяться на bkcustom при размещении в Default значения True и наоборот - в Default автоматически помещается False при установке в Kind любого значения, кроме bkYes, bkNo или bkcus-tom.

18.2.2. TSpeedButton - кнопка для инструментальных панелей

Кнопки TSpeedButton отличаются от TBitBtn Тремя обстоятельствами: во-первых, они могут фиксироваться в утопленном состоянии, во-вторых, они не могут закрыть модальное окно в третьих, они не могут быть умалчиваемыми. Во всем остальном они повторяют свойства и методы TBitBtn.

Для фиксации кнопка должна быть отнесена к какой-либо группе кнопок (эта группа может состоять из нее одной - вариант одиночной фиксируемой кнопки). Для этого используется свойство GroupIndex: Integer, которое не должно быть равно 0. Поведение кнопки определяется логическим свойством AllowAllup: если это свойство имеет значение True, утопленная кнопка отпускается только при нажатии любой другой кнопки, входящей в ту же группу; если AllowAllup=False, кнопку можно освободить повторным щелчком. Индикатором состояния кнопки служит логическое свойство Down, которое имеет значение True, если кнопка утоплена. Свойство доступно для записи, что позволяет изменять состояние кнопки программно.

Для кнопки TSpeedButton предусмотрено событие onDbiciick, которое возникает при двойном щелчке на утопленной кнопке.

18.2.3. TMaskEdit - специальный редактор

Специализированный редактор TMaskEdit предназначен для ввода текста, соответствующего некоторому шаблону, задаваемому свойством EditMask: String. Если это свойство не задано, TMaskEdit работает как обычный редактор TEdit. Свойство IsMasked: Boolean доступно только для чтения и содержит True, если строка шаблона задана. Свойство EditText: string содержит текст до наложения на него маски шаблона (т. е. то, что ввел пользователь), а свойство Text: String может (в зависимости от шаблона см. ниже) содержать либо исходный текст, либо результат наложения на него маски шаблона.

Шаблон состоит из трех частей, отделенных друг от друга символами “;”. Первая часть задает маску ввода, вторая - это символ “О” или “I”, определяющий, записывается ли в Text результат наложения маски или исходный текст (“О” - исходный текст). В третьей части указывается символ, который в окне редактора будет стоять в полях, предназначенных для ввода символов (текст в редакторе может содержать символы маски; например, для ввода семизначного номера телефона текст в начале ввода может выглядеть так: (095)ХХХ-ХХ-ХХ где доступные для ввода пользователя поля указаны символом “X” -последним символом в шаблоне).

Маска состоит из описателей полей ввода, специальных символов и литералов. Описатель указывает, какой именно символ может ввести пользователь в данное поле (описатель всегда описывает поле единичной длины, т. е. рассчитанное на ввод одного символа). Литерал вставляется в текст, показываемый в окне редактора, но при вводе курсор перескакивает через литерал и не дает пользователю возможности изменить его. Литералами считаются любые символы, кроме описателей полей и специальных символов, а также любой символ, которому предшествует символ “\”. Специальные символы формируют дополнительные указания редактору.

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

Символ Поле...

L должно содержать букву

с может содержать любой символ

1 может содержать букву

0 должно содержать цифру

А должно содержать букву или цифру

9 может содержать цифру

а может содержать букву или цифру

# может содержать цифру, “+”, “-”

С должно содержать любой символ

Специальные символы:
\ | Следующий символ - литерал. Позволяет вставить в маску литералы из символов описателей полей ввода и специальных символов
: | На это место вставляется символ-разделитель Windows для часов, минут, секунд
/ | На это место вставляется символ-разделитель Windows для полей даты
; | Разделитель частей шаблона
! | Подавляет все ведущие пробелы
> | Все следующие за ним поля ввода преобразуют буквы к заглавным
< | Все следующие за ним поля ввода преобразуют буквы к строчным
<> | Отменяет преобразование букв

Примеры:

Маска | Вид в редакторе | Свойство EditText | Свойство Text
(095)000-0000;0;х | (095)ххх-хххх | 123456 | 1234567
(095)0000000;1;х | (095)ххх-хххх | 7 12345 | (095)1234567
(095)\0\00-0000;1; . | (095)00.-.... | 1234567 | (095)0012345

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

Остальные свойства компонента повторяют соответствующие свойства TEdit. В частности, установка в свойство passwordchar любого символа, кроме #0, обеспечивает секретность ввода: в этом случае все вводимые в компоненте символы заменяются символом PasswordChar.

18.2.4. TStringGrid - таблица строк

Компонент TStringGrid предназначен для создания таблиц, в ячейках которых располагаются произвольные текстовые строки. Он является прямым потомком TDrawGrid (см. ниже п. 18.2.5), от которого им унаследовано большинство свойств и методов.

Таблица делится на две части - фиксированную и рабочую. Фиксированная служит для показа заголовков столбцов/рядов и для ручного управления их размерами. Обычно фиксированная часть занимает крайний левый столбец и самый верхний ряд таблицы, однако с помощью свойств FixedCols и FixedRows можно задать другое количество фиксированных столбцов и рядов (если эти свойства имеют 0, таблица не содержит фиксированной зоны). Рабочая часть - это остальная часть таблицы. Она может содержать произвольное количество столбцов и рядов, более того, эти величины могут изменяться программно. Рабочая часть может не умещаться целиком в пределах окна компонента, в этом случае в него автоматически помещаются нужные полосы прокрутки. При прокрутке рабочей области фиксированная область не исчезает, но меняется ее содержимое - заголовки строк и рядов.

Центральным свойством компонента является Cells - двухмерный массив ячеек, каждая из которых может содержать произвольный текст. Конкретная ячейка определяется парой чисел - номером столбца и номером ряда, на пересечении которых она находится (нумерация начинается с нуля). Свойство cells имеет тип String, поэтому программа может легко прочитать или записать содержимое нужной ячейки. Например:

Cells [1,1] := 'Левая верхняя ячейка рабочей зоны';

Количество ячеек по каждому измерению хранит пара свойств Colcount (количество столбцов) и RowCount (количество рядов). Значения-этих свойств и, следовательно, размеры таблицы могут меняться как на этапе разработки программы, так и в ходе ее работы, однако их значения должны быть как минимум на единицу больше соответственно значений в свойства FixedCois и FixedRows, определяющих размеры фиксированной зоны.

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

Свойства компонента:

property BorderStyle: TBorderStyle; | Определяет рамку компонента: bsNone нет рамки; bsSingle - рамка толщиной 1 пиксель
property Cells[ACol, ARow: Integer] :String; | Определяет содержимое ячейки с табличными координатами (ACol, ARow)
property Col: Longint; | Содержит номер столбца сфокусированной ячейки
property ColCount: Longing- | Содержит количество столбцов таблицы
property Cols[Index: Integer]: TStrings; | Содержит все строки колонки с индексом Index
property ColWidths[Index: Longint] : Integer; | Содержит ширину столбца с индексом Index
property DefaultColWidth: Integers; | Содержит умалчиваемое значение ширины столбца
property DefaultDrawing: Boolean; | Разрешает/запрещает автоматическую прорисовку служебных элементов таблицы - фиксированной зоны, фона и прямоугольника сфокусированной ячейки и т. п.
property DefaultRowHeight: Integers; | Содержит умалчиваемую высоту рядов
property EditorMode: Boolean; | Разрешает/запрещает редактирование ячеек. гнорируется, если свойство Options включает goAlwayseShowEditor или не включает goEditing
property FixedColor: TColor; | Определяет цвет фиксированной зоны
property FixedCois: Integers; | Определяет количество столбцов фиксированной зоны
property FixedRows: Integers; | Определяет количество рядов фиксированной зоны
property GridHeight: Integers; | Содержит высоту таблицы
property GridLineWidth: Integers; | Определяет толщину линий, расчерчивающих таблицу
property GridWidth: Integers; | Содержит ширину таблицы
property LeftCol: Longint; | Содержит номер самого левого столбца, видимого в зоне прокрутки
property Objects [ACols ARow: Integer] : TObject; | Обеспечивает доступ к объекту, связанному с ячейкой (ACol, ARow)
property Options: TGridOptions; | Содержит параметры таблицы (см. ниже)
property Row: Longing; | Содержит номер ряда сфокусированной ячейки
property RowCount: Longint; | Содержит количество рядов таблицы
property RowHeights[Index: Long int] : Integer; | Содержит высоту ряда с индексом index
property Rows[Index: Integer]: TStrings; | Содержит все строки ряда с индексом Index
type TScrollStyle = (ssNone, ssHorizontal, ssVertical, ssBoth) ; | Определяет полосы прокрутки: ssNone -нет полос; ssHorizontal - в таблицу вставляется горизонтальная полоса;
property ScrollBars: TScroll Style; | ssVertical - вставляется вертикальная полоса; ssBoth - вставляются обе полосы

TGridRect = record

case Integer of

0: (Left,Top,Right,Bottom: Long int) ;

1: (TopLeft,

BottomRight: TGridCoord) ;

end;

Определяет группу выделенных ячеек в

координатах левая верхняя и правая

нижняя ячейки(нумерация столбцов и рядов идет от нуля, включая столбцы и

ряды фиксированной зоны). После выделения сфокусированной окажется правая нижняя ячейка

property Selection: TGridRect; property TabStops[Index: Long int] : Boolean; | Разрешает/запрещает выбирать столбец с индексом index при обходе ячеек клавишей Tab. Игнорируется, если Options не содержит goTabs
property TopRow: Longint; | Содержит номер самого верхнего ряда, видимого в прокручиваемой зоне ячеек
property VisibleColCount: Integer; | Содержит количество столбцов, полностью видимых в зоне прокрутки
property VisibleRowCount: Integer; | Содержит количество рядов, полностью видимых в зоне прокрутки

Для компонента определен тип TGridOptions:

type

TGridOption = (goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goDrawFocusSelected, goRowSizing, goColSizing, goRowMoving, goColMoving, goEditing, goTabs, goRowSelect, goAlwaysShowEditor, goThumbTracking);

TGridOptions = set of TGridOptions;

Элементы множества TGridOptions имеют следующий смысл:

goFixedVertLine | Столбцы фиксированной зоны разделяются вертикальными линиями
goFixedHorzLine | Ряды фиксированной зоны разделяются горизонтальными линиями
goVertLine | Столбцы рабочей зоны разделяются вертикальными линиями
goHorzLine | Ряды рабочей зоны разделяются горизонтальными линиями
goRangeSelect | Разрешено выделение нескольких ячеек. Игнорируется, если включен элемент goEdit
goDrawFocus Selected | Разрешено выделять сфокусированную ячейку так же, как выделенные
goRowSizing goColSizing goRowMoviog | Разрешено ручное (мышью) изменение высоты строк Разрешено ручное изменение ширины рядов Разрешено ручное перемещение рядов (нажать левую кнопку мыши на фиксированной ячейке перемещаемого ряда и, удерживая кнопку нажатой, переместить ряд на новое место)
goColMoving goEditing | Разрешено ручное перемещение столбца Разрешено редактирование ячейки. Игнорируется, если включен элемент goRowSelect. Редактирование начинается после щелчка мыши или нажатия клавиши F2 и завершается при щелчке по другой ячейке или нажатии клавиши Enter
goTabs goRowSelect | Разрешено обходить ячейки клавишей Tab (Shift+Tab) Обязывает выделять сразу все ячейки ряда и запрещает редактирование ячеек Разрешено редактировать сфокусированную ячейку: редактирование возможно после выбора ячейки клавишей Tab (Shift+Tab). Игнорируется, если не включен элемент goEditing
goAlwaysShowEditorgoThumbTracking | Разрешено обновление при прокрутке. Если этот элемент отсутствует, обновление ячеек произойдет только после окончания прокрутки

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

function CellRect(ACol, ARow: TRect; Longint): | Возвращает прямоугольник ячейки по номерам столбца ACol и ряда Arow
procedure MouseToCell(X, Y: Integer; var ACol, ARow: Longint); | Возвращает табличные координаты ячейки ACol и arow по экранным координатам(X,У)точки

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

TMovedEvent = procedure (Sender: TObject; Fromlndex, Tolndex: Longint) of object; property OnColumnMoved: TMovedEvent; TDrawCellEvent; | Возникает при перемещении столбца с индексом Fromlndex в положение, определяемое индексом ToIndex
TGridDrawState = set of (gdSelected, gdFocused, gdFixed) ; TDrawCellEvent = procedure (Sender: TObject; Col, Row: Longint; Rect: TRect; State: TGridDrawState) of object-property OnDrawCell: | Возникает при необходимости перерисовать ячейку с табличными координатами (Col, Row): Rect - прямоугольник прорисовки; State - состояние ячейки (gdSelected -ячейка выделена; gdFocused - ячейка сфокусирована; gdFixed - ячейка принадлежит фиксированной зоне таблицы). Для прорисовки используется табличное свойство Canvas
GetEditEvent = procedure (Sender: TObject; ACol, ARow: | Возникает при редактировании текста в ячейке с табличными координатами
Longint; var Value: String) ofobject; property OnGetEditMask: TGetE ditEvent; | (ACol.ARow). В параметре value обработчик должен вернуть шаблон для редактора TeditMask
property OnGetEditText: TGetE ditEvent; | Возникает при редактировании текста в ячейке с табличными координатами (ACol.ARow). В параметре value обработчик должен вернуть текст для редактора TEditMask (см. событие OmGetEditMask)
property OnRowMoved: TMovedEvent; | Возникает при перемещении ряда с индексом Fromindex в положение, определяемое индексом ToIndex (см. событие onColMoved)
SelectCellEvent = procedure (Sender: TObject; Col, Row: Long int; var CanSelect: Boolean) of object; property OnSelectCell: TSe lectCellEvent; | Возникает при попытке выделить ячейку с табличными координатами (col.Row). В параметре CanSelect обработчик сообщает о возможности выделения ячейки
TSetEditEvent = procedure (Sender: TObject; ACol, ARow: Longint; const Value: String) of object; property OnSetEditText: TSetEditEvent; | Возникает при завершении редактирования ячейки (ACol.ARow). В параметре value обработчик получает результат ввода или редактирования текста
property OnTopLeftChanged: TNotifyEvent; | Возникает после изменения значения ТоpRow или LeftCol в результате прокрутки рабочей зоны

В следующем примере компонент TStringGrid используется для показа всех слов из произвольного текстового файла (рис. 18.10).

- Назовите пустую форму именем fmStGrid и положите на нее панель TPanel.
- Установите в свойство панели Align значение alBottom, чтобы панель всегда занимала самую нижнюю часть окна, и удалите текст в ее свойстве caption.
- Поместите на панель кнопку TBitBtn, установите в ее свойство

Caption строку Открыть файл..., загрузите в свойство Glyph файл images | buttons | FILE OPEN.BMP и растяните кнопку по горизонтали так, чтобы надпись и пиктограмма полностью умещались на ее поверхности.

Рис. 18.10. Пример использования TStringList

- Поместите на панель еще одну кнопку TBitBtn и установите в ее свойство Kind значение bkClose.
- Поместите на панель компонент OpenDialog из страницы компонентов Dialogs. Этот компонент создает и обсуживает стандартное для Windows окно открытия файла. С его помощью при прогоне программы вы сможете выбрать текстовый файл (например, файл с текстом программы), чтобы программа показала в таблице все слова из этого файла.
- На форму (а не на панель panel1) положите компонент TStringGrid.
- Поместите в его свойства ColCount и RowCount значения 2 (количество колонок и рядов таблицы должно быть больше, чем количество фиксированных колонок FixedCois и количество фиксированных рядов FixedRows). Установите в свойство Align компонента значение alClient, чтобы он занял все свободное место формы.

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

Создайте такой обработчик события OnClick для кнопки BitBtn1:

procedure TfmStGrid.BitBtnIClick(Sender: TObject) ;

Function GetWord(var S: String): String;

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

строки }

const // Множество символов слова:

Letters: set of Char = ['a'..'z', 'A'..'Z', 'A'..'я'];

begin

Result := '' ;

{ Уничтожаем в начале строки все символы, не относящиеся к слову }

while (S о '') and not (S[1] in Letters) do

Delete (S, 1, 1);

// Формируем очередное слово

while (S<> '') and (S[1] in Letters) do

begin

Result := Result + S[1];

Delete (S, 1, 1)

end;

end; //Get Word

var

F: TextFile; // Файл с текстом S,

Word: String; // Вспомогательные строки

NCol, NRow: Integer;// Номер текущей колонки и текущего ряда Words: TStringList; // Список отсортированных слов из файла

begin

// С помощью стандартного диалога получаем имя файла

if not OpenDialogI.Execute then

Exit; // Пользователь отказался выбрать файл

// Пытаемся открыть файл

AssignFile(F, OpenDialogI.FileName) ;

try

Reset(F) ;

except

// Файл нельзя открыть:

ShowMessage('Невозможно открыть файл ' +OpenDialogI.FileName) ;

Exit;

end;

// Готовим список Words:

Words := TStringList.Create;

Words.Sorted := True; // Сортируем строки Words.Duplicates := duplgnore; // Отвергаем дубликаты

// Изменяем курсор перед длительной работой

Screen.Cursor := crHourGlass;

// Читаем файл по строкам

while not EOF(F) do

begin

ReadLn(F, S); // Читаем очередную строку

// Выделяем из строки слова и заносим их в список Words

while S о '' do

begin

Word := GetWord(S) ;

if Word о '' then

Words.Add(Word) // He вставляем пустые строки

end

end;

Screen.Cursor := crDefault; // Восстанавливаем курсор

CloseFile(F); // Закрываем файл

if Words.Count=0 then

Exit; // Пустой файл - выходим

with sgWords do

begin

NCol := 1; // Номер первого столбца слов

// Цикл формирования таблицы

while Words.Count > 0 do

begin

{Формируем заголовок столбца и начальное значение номера ряда}

Cells [NCol, 0] := Words[0][1];

NRow := О

// Цикл заполнения очередного столбца

while (Words.Count > 0) and

(Words[0][1] = Cells[NCol, 0]) do

begin

inc(NRow); // Номер текущего ряда

if NRow = RowCount then

begin // Расширяем длину таблицы

RowCount := RowCount + 1;

{Для свойства RowCount нельзя, использовать функцию инкремента inc!} Cells [0, NRow] := IntToStr(NRow);

end;

Cells[NCol, NRow] :=Words[0];

Words.Delete(0) ;

end;

// Переходим к следующему столбцу

if Words.Count=0 then

Break; // Кончаем работу, если слов больше нет

inc(NCol); // Переходим к следующей колонке

ColCount := ColCount+1 // Расширяем таблицу справа

//на 1 колонку

end;

end;

end;

18.2.5. TDrawGrid - произвольная таблица

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

Чтобы таблица была работоспособной, в ней как минимум следует определить обработчик события OnDrawCell, которое возникает при необходимости прорисовать ту или иную ячейку. Для прорисовки используется табличное свойство Canvas.

Компонент TDrawGrid является непосредственным родителем строковой таблицы TStringGrid, поэтому передает ей все свои свойства, методы и события за исключением специфичных для строк свойств Cells, Cols, Objects И Rows. Поскольку порядок описания компонентов в этой главе соответствует умалчиваемому порядку их расположения на страницах палитры компонентов, TStringGrid описан раньше своего родителя TDrawGrid, и вы сможете найти информацию о свойствах, методах и событиях последнего в предыдущем параграфе.

В следующем примере компонент TDrawGrid используется для показа текста и картинок одновременно, причем текст можно редактировать. Картинки взяты из каталога images l splash | igcolor (рис. 18.11).

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

Если вы захотите повторить пример, следует сначала подготовить пустую форму главного окна. Дайте ей имя fmDrawGrid и вставьте в описание класса TfmDrawGrid такое поле:

public

sIBitMap: TSringList;

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

procedure TfmDrawGrid.FormCreate(Sender: TObject);

// Создает и наполняет список sIBitMap

const

FNames: array [0..3] of String = {Имена файлов с картинками} ('athena.bmp', 'construe.bmp', 'earth.bmp', 'technlgy.bmp');

var

k: Integer;

begin

// Создаем список строк:

sIBitMap := TStringList.Create;

// Вставляем в него названия файлов и картинки:

with sIBitMap do for k := 0 to 3 do

begin

Add(FNames[k]) ;

Objects[k] := TBitMap.Create;

(Objects[k] as TBitMap).LoadFromFile(FNames[k])

end;

end;

procedure TfmDrawGrid.FormDestroy(Sender: TObject);

// Уничтожает список строк

begin

sIBitMap.Free

end;

Обратите внимание: в именах файлов нет маршрута поиска, поэтому следует скопировать файлы, перечисленные в константе FNames, из каталога images | splash | 16 color в каталог для размещения ваших учебных программ и в этом же каталоге сохранить форму fmDrawGrid и проект под именем DrawGrid. После этого полезно осуществить прогон программы, чтобы убедиться в доступности файлов. Если при прогоне появится сообщение cannot open file, еще раз убедитесь в том, что файл drawgrid. exe создан в том же каталоге, в котором находятся вмр-файлы.

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

Свойство | Значение | Комментарий
Align | alClient | Таблица занимает всю клиентскую часть окна
ColCount | 2 | В таблице 2 колонки
FixedCols | 0 | Нет фиксированных колонок
FixedRows | 0 | Нет фиксированных рядов
Name | dgDraw | Имя таблицы
Options.goEditing | True | Разрешено редактирование текста
RowCount | 2 | В таблице 2 строки
ScrollBars | sbNone | He надо вставлять полосы прокрутки

Теперь необходимо создать обработчики событий OnGetEditText, OnSetEditText иOnDrawCell. Два первых используются для редактирования текста, а обработчик OnDrawCell обязательно создается для любого компонента TDrawGrid, т. к. без него компонент не сможет заполнить пустые клетки каким-либо изображением или текстом.

procedure TfmDrawGrid.DrawGridlGetEditText(Sender: TObject;

ACol, ARow: Integer;

var Value: String ) ;

// Передает редактору текст из ячейки

begin

Value := slBitMap[2 * ACol + Arow]

end;

procedure TfmDrawGrid.DrawGridlSetEditText(Sentier: TObject;

ACol, ARow: Integer; const Value: String ) ;

// Получает текст из редактора и сохраняет его в sIBitMap

begin

slBitMap[2 * ACol + ARow] := Value

end;

procedure TfmDrawGrid.dgDrawDrawCell(Sender: TObject;

Col, Row: Integer; Rect: TRect; State: TGridDrawState) ;

// Рисует картинку из sIBitMap.Objects и текст из sIBitMap

var

k: Integer;

begin

// Пересчитываем координаты ячейки в индекс списка:

k := 2 * Col + Row;

with dgDraw.Canvas, Rect, sIBitMap do

begin

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

Bottom := Bottom - TextHeight('1') - 2;

// Рисуем картинку:

StretchDraw(Rect, (Objects[k] as TBitMap)) ;

// Центрируем текст по горизонтали и выводим его:

TextOut(Left+(Right-Left-TextWidth(sIBitMap[k])) div 2,

Bottom + 1, slBitMap[k])

end

end;

Осталось добиться того, чтобы размеры ячеек таблицы согласовывались с размерами окна программы. Для этого создайте для формы fmDrawGrid такой обработчик события onResize (это событие возникает при каждом изменении размеров окна):

procedure TfmDrawGrid.FormResize(Sender: TObject);

// Изменяет размеры ячеек при изменении размеров окна.

// Запас в один пиксель необходим для предотвращения

// автопрокрутки

begin

with dgDraw do

begin

DefaultColWidth := ClientRect. Right div 2-1;

DefaultRowHeight := ClientRect. Bottom div 2-1

end;

end;

18.2.6. TImage - отображение картинок

Этот компонент служит для размещения на форме одного из трех поддерживаемых Delphi типов изображений: растровой картинки, пиктограммы или метафайла. Любой из этих типов изображения содержится в центральном свойстве компонента - picture. В свойстве canvas содержится канва, с помощью которой при необходимости программа может отредактировать растровое изображение (но не пиктограмму или метафайл!).

Вот как можно создать несложный просмотрщик изображений, окно которого показано на рис. 18.12:

- Поместите на форму панель TPanei, очистите ее свойство caption и поместите значение alBottom в свойство Alignment - панель займет нижнюю часть формы.
- Разместите на панели кнопку TButton с надписью загрузить.
- На любое свободное место формы (над панелью) поместите компонент Timage и установите в его свойство Align значение alClient.
- На любое место (Timage, TPanei или даже TButton) поместите cтандартный диалог TOpenPictureDialog (страница Dialogs палитры компонентов) - с его помощью пользователь вашей программы сможете разыскать нужный файл с изображением.

Рис. 18.12. Компонент Tfmage воспроизводит изображение

- Напишите такой обработчик события onСlick для кнопки Button1:

procedure TFormI.ButtonlClick(Sender: TObject) ;

begin

if OpenPictureDialogI.Execute then

begin

Imagel.Picture.LoadFromFile
(OpenPictureDialogI.FileName);

Imagel.Stretch := True

end

end;

Замечу, что оператор

Imagel.Stretch := True

масштабирует изображение так, чтобы оно занимало всю рабочую область TImage.

Свойства компонента:

property Center: Boolean; | Указывает, надо ли центрировать изображение в границах компонента. Игнорируется, если Autosize=True или если Stretch =True и изображение не является пиктограммой (ICO)
property Canvas : TCanvas; | Содержит канву для прорисовки изображения
property Transparent: Boolean; | Запрещает/разрешает накладывать собственный фон изображения на фон компонента
property Proportional: Boolean;property Stretch: Boolean; | Разрешает/запрещает изменять размер изображения так, чтобы оно целиком заполнило клиентскую область компонента
property Picture: TPicture; | Разрешает/запрещает пропорционально уменьшать высоту и ширину изображения, если оно не может целиком уместиться в рабочей зоне компонента
property IncrementalDisplay: Boolean; | Разрешает/запрещает показ большого изображения по мере его загрузки Центральное свойство класса. Служит контейнером изображения

С помощью методов класса TPicture (см. п. 16.5.5), к которому относится свойство picture, программист может загрузить изображение из файла или буфера межпрограммного обмена clipboard и сохранить его в файле или буфере.

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

type TProgressStage = (psStarting, psRunning, psEnding) ;

TProgressEvent = procedure (Sender: TObject;

Stage: TProgressStage; PercentDone: Byte;

RedrawNow: Boolean;

const R:

TRect; const Msg: String ) of object;

property OnProgress: TProgressEvent

Параметр stage содержит состояние процесса загрузки (psStarting - начало, psRunning - идет загрузка, psEnding - процесс завершен). Параметр PercentDone приблизительно указывает процент выполненной работы. С помощью параметра RedrawNow Windows сообщает, нужно ли сейчас выполнить прорисовку части изображения. Этот параметр имеет смысл, только если свойство incrementaiDis-play компонента содержит True. r - прямоугольник, нуждающийся в прорисовке. Msg содержит одно или более слов, уточняющих состояние процесса. Обычно в обработчике события по сигналу psStarting создается индикатор процесса типа TprogressBar, по сигналам psRunning изменяется позиция индикатора, а в момент psEnding индикатор уничтожается. Следует учесть, что событие onprogress создается только при загрузке некоторых типов изображений, например, подготовленных в формате JPEG (Joint Photographic Expert Group - объединенная группа фотографических экспертов) [ Для поддержки JPEG в Delphi включен специальный класс TJPEGImage. Пример использования этого класса, а также события OnProgress вы найдете в программе help\examples\jpeg\jpegproj.dpr каталога размещения Delphi. ].

18.2.7. TShape - стандартная фигура

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

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

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

Помимо стандартных чертежных инструментов Brush и pen (шрифт для компонента не нужен) в компоненте определено свойство shape.' TShapeType, которое и задает вид геометрической фигуры. Изменение этого свойства приводит к немедленной перерисовке изображения.

18.2.8. TBevel - кромка

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

type TBevelShape = (bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine, bsRightLine);

property Shape: TBevelShape;

определяет вид компонента (прямоугольник, рамка, верхняя линия, нижняя линия, левая линия, правая линия).

Свойство

type TBevelStyle = (bsLowered, bsRaised) ;

property Style: TBevelStyle;

задает стиль компонента (вдавленный или выпуклый).

18.2.9. TScrollBox - панель с прокруткой

Компонент класса TScrollBox служит контейнером для размещения других компонентов. Его отличительная особенность - возможность прокрутки и, следовательно, экономия пространства формы при необходимости размещения на ней большого количества управляющих элементов. Замечу, что современные программные продукты относительно редко используют такого рода компоненты, отдавая предпочтение многолистным блокнотам с закладками. Наиболее походящей областью применения компонентов является размещение на них относительно длинных TEdit, TComboBox, TMemo И Т. П.

Использование компонента не отличается сложностью: положите его на форму и размещайте затем на нем другие компоненты. Если очередной компонент выйдет за пределы рабочей области TScrollBох, по сторонам контейнера возникнут полосы прокрутки (рис. 18.13).

Однако если свойство AutoScroll компонента содержит False, полосы прокрутки не появятся, и компонент будет отсекать “лишние” части своих дочерних компонентов. Еще одним важным свойством компонента является AutoSize: если это свойство имеет значение True, размеры компонента будут автоматически изменяться так, чтобы все части дочерних компонентов были в его рабочей зоне, даже если для этого придется увеличить размеры внешнего контейнера (формы). С помощью свойств HorzScrollBar и VertscrollBar программист может управлять свойствами каждой из полос прокрутки в отдельности (свойства класса TControlScrolBar, к которому они принадлежат, описаны в п. 18.1.1).

Рис. 18.13. Размещение компонентой на TScrollBox

18.2.10. TcheckListBox - группа независимых переключателей

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

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

Свойства компонента:

property AllowGrayed: Boolean; | Разрешает/запрещает использовать в переключателях третье состояние cbGrayed
property BorderStyle: TBorderStyle; | Определяет тип рамки, очерчивающей компонет: bsNone - нет рамки; bsSingie - рамка толщиной в 1 пиксель
property Canvas: TCanvas; | Это свойство используется для программной прорисовки опций
property Checked[Index: Integer]: Boolean; | Содержит выбор пользователя типа Да/Нет для переключателя с индексом index. Состояния cbUnchecked И cbGrayed отражаются как False
property Columns: Integers; | Определяет количество колонок опций
property Flat: Boolean; | Разрешает/запрещает трехмерную прорисовку окошек выбора
property Header[Index: Integer] : Boolean; | Запрещает прорисовку окошка выбора для опции с индексом index. Таким образом вставляются заголовки отдельных секций

property HeaderBackgroundColor: TColor; | Цвет фона для заголовка (см. свойство Header)
property HeaderColor:TColor; | Цвет текста для заголовка (см. свойство Header)
property IntegralHeight: Boolean; | Если имеет значение True, компонент автоматически изменяет высоту так, чтобы в нем полностью отображались опции, в противном случае последняя опция может не полностью отображаться в окне компонента
property ItemEnabled[Index: Integer]: Boolean; | Разрешает/запрещает выбор опции с индексом Index
property ItemHeight: Integer; | Если свойство Style компонента имеет значение IsOwnerDrawFixed, значение ItemHeight Определяет высоту каждой опции компонента. При других значениях Style это свойство игнорируется
property Itemlndex: Integer; | Содержит индекс выбранной опции (индексация опций начинается с нуля)
property Items: TStrings; | Содержит опции компонента
property MultiSelect: Boolean; | Если содержит True, пользователь может выбирать несколько опций
property SelCount: Integer; | Содержит количество выбранных опций компонента, если свойство MultiSelect содержит True
property Selected[Index: Integer]: Boolean; | Содержит True, если опция с индексом index выбрана
property Sorted: Boolean; | Сортирует по алфавиту надписи на переключателях
property State[Index: Integer] : TCheckBoxState; | Содержит состояние переключателя с индексом Index: cbUnchecked - нет; cbChecked ~ да; cbGrayed - не совсем
type TListBoxStyle = (IbStandard, IbOwnerDraw- Fixed, IbOwnerDrawVariable); | Определяет способ прорисовки опций компонента: IbStandard - опции прорисовывает Windows; ibOwnerDrawFixed - компонент использует программный метод прорисовки опций, каждый из
property Style: TListBox Style; | которых имеет одинаковую высоту ItemHeight; IbOwnerDrawVariable - опции прорисовываются программно и могут иметь разную высоту
property TabWidth: Integer; | Определят ширину табулостопов
property Toplndex: Integer; | Содержит индекс самой первой отображаемой опции

Для компонента определено событие

property OnClickCheck: TNotifyEvent;

которое наступает при изменении состояния любого переключателя.

18.2.11. TSplitter - компонент для изменения размеров

Компонент TSplitter предназначен для ручного (с помощью мыши) управления размерами контейнеров TPanel1, TGroupBox или подобных им во время прогона программы. Визуально он представляет собой небольшую вертикальную или горизонтальную полосу, располагающуюся между двумя соседними контейнерами или на “свободной” стороне одного их них.

Непременным условием правильной работы компонента является выравнивание контейнера (контейнеров), размерами которого (которых) он управляет, вдоль одной из сторон окна или охватывающего контейнера. Для примера на рис. 18.14 показаны две панели, разделенные компонентом TSpiitter. Нижняя панель имеет Align = alBottom, верхняя в этом случае может иметь выравнивание alBottom или alciient. Между ними помещен TSplitter с выравниванием alBottom.

Свойства компонента:

property Beveled: Boolean; | Управляет трехмерным изображением компонента. Если False, компонент виден как узкая полоска фона между разделяемыми им компонентами него

NaturalNumber = 1..High(Integer) ; | Содержит минимальный размер любого из компонентов, которые разделяет TSplitter.
property MinSize: Natural-Number; | Если выравнивание aiLeft или aiRight - минимальная ширина компонента слева и справа от TSplitter, еСЛИ alTop или alBottom -минимальная высота компонента выше или ниже отнего

Для компонента определено событие onMoved, которое вызывается при любом перемещении компонента мышью.

Рис. 18.14 . Пример использования компоненты TSplitter (помечен черными квадратиками)

18.2.12. TStaticText - метка для отображения текста

Этот компонент во всем подобен своему “двоюродному брату” TLabel за исключением двух обстоятельств. Во-первых, он порожден от TwinControl и, таким образом, имеет Windows-окно. Это обстоятельство может быть необходимым условием правильного взаимодействия со связанным свойством FocusControl управляющим элементом, если это внешний для Delphi элемент ActiveX. Во-вторых, в его свойстве

type TStaticBorderStyle = (sbsNone, sbsSingle, sbsSunken) ;

property BorderStyle: TStaticBorderStyle;

добавлено значение sbsSunken, которое создает иллюзию “вдавлен-ности” компонента. Все остальные свойства и методы компонента совпадают со свойствами и методами TLabel.

18.2.13. TControlBar - инструментальная панель

Компонент служит удобным контейнером для размещения инструментальных панелей TTооlBаr (см. п. 18.3.16). Он активно использует технологию Drag&Dock для управления положением панелей. На рис. 18.15 показан компонент TControlBar с двумя помещенными на него панелями TTооlваг.

Если вы захотите повторить пример, проделайте следующее.

- Создайте новое приложение с пустой формой и положите на нее компонент ControlBar.

Рис 18.15. Пример использования компонента TControlBar

- Установите в его свойство Align значение alTip, в AutoSize- True, в DradKind-dkDragMode. Оставьте в свойстве DragMode значение dmManual.
- Положите на свободное место формы два компонента ImageList (страница Win 32 палитры компонентов) и наполните кождый из них двумя тремя изображениями.
- В появившемся окне редактора (рис. 18.16) нажмите кнопку Add и выберите любой вмр-файл из каталога images\Buttons[ См. замечание в начале главы. ]. Файлы в этом каталоге имеют по два изображения, в то время как компонент ImageList способен хранить только одиночные изображения одинакового размера. Поэтому редактор предложит вам разделить два изображения - согласитесь с ним (кнопка ок). Щелкните по правому изображению в окне редактора (оно предназначено для отображения кнопки в запрещенном состоянии) и нажмите кнопку Delete, чтобы уничтожить его.
- Повторите п. 4 для загрузки нескольких изображений и затем закройте редактор.
- Поместите на компонент ControlBar1 компонент TooiBar (страница Win32). Компонент TooiBari, попав на панель соп-troiBari, для версии Delphi 4.0 сразу сожмется по горизонтали (для более поздних версий 4.5, 5 и 6 этого не произойдет). В этом случае установите в его свойство width значение 20, чтобы несколько растянуть его, иначе вы не сможете щелкнуть по нему правой кнопкой мыши.

Рис. 18.16 . Окно редактора ImageList

- Установите в свойство images компонента TooiBar1 значение ImageList1 и поместите в него столько кнопок, сколько изображений вы подготовили в imageList1. Для вставки кнопки щелкните по TooiBar1 правой кнопкой мыши и выберите опцию NewButton.
- Поместите на свободное место формы еще один компонент ToolBar. Он автоматически прижмется к нижнему краю СоntrolBar1.Измените в его свойстве Align значение alTop на а1None и мышью сместите компонент несколько вниз - на этапе прогона программы этот компонент будет “причаливать” к ControlBar1. Свяжите компонент С ImageList2 (свойство Images) и создайте в нем кнопки (см. п. 7).
- Для обоих компонентов поместите в свойства DragKind значения dkDock, В DragMode - dmAutomatic И В AutoSize — True.
- Запустите программу и перетащите нижнюю панель кнопок на ControlBar1.

Свойства компонента:

property AutoDrag: Boolean; | Разрешает/запрещает компонентам ToolBar покидать границы controlBar
property Picture: TPicture; | Содержит изображение, которое, периодически повторяясь, создает фон компонента
property RowSize: TRowSize; | Задает высоту одного ряда инструментальных панелей. Умалчиваемое значение 25 в точности соответствует высоте одной панели и в этом случае между рядами нет зазора
property RowSnap: Boolean; | Если содержит True, “причаливаемая” панель будет выравниваться по высоте ряда

Метод

procedure StickControls; virtual;

устанавливает все дочерние компоненты на их окончательные позиции после “причаливания” или “отчаливания” очередной инструментальной панели. Его нужно перекрыть, если стандартное размещение панелей по каким-либо причинам вас не устраивает;

События компонента:

TBandInfoEvent = procedure(Sender: TObject; Control: TControl; var Insets: TRect; var PreferredSize, RowCount: Integer) of object-property OnBandInfo: TBandInfoEvent; | Возникает при перемещении панели внутри компонента: Sender - компонент; control - панель; insets - зазор между сторонами компонента и панели; Рге-ferredsize - предпочтительная ширина панели; RowCount - количество рядов панелей
TBandMoveEvent = procedure (Sender: TObject; Control: TControl; ARect: TRect) of object/property OnBandMove: TBandMoveEvent; | Возникает при перемещении панели " внутри компонента: Sender - компонент; Control - панель; ARect - прямоугольник для размещения панели
TBandPaintEvent = procedure (Sender: TObject; Control: TCon-tro,l; Canvas: TCanvas; var ARect: TRect; var Options: TBandPaintOp-tions) of object; property OnPaint: TNotifyEvent; | Возникает при необходимости прорисовки панели: sender - компонент; Control - панель; Canvas - канва для прорисовки; ARect - прямоугольник прорисовки; Options - определяет, какая часть панели нуждается в прорисовке Возникает при необходимости прорисовки компонента

18.2.14. TApplicationEvents - обработчик сообщений Windows

Компонент TApplicationEvents впервые введен в версии Delphi 5. В отличие от остальных компонентов страницы Additional он не имеет видимого эквивалента в работающей программе. Его основное и единственное назначение - служить приемником многочисленных сообщений, которые windows посылает работающей программе.

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

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

- На пустую форму поместите TEdit И TApplicationEvents.
- Напишите такой обработчик события OnMessage компонента TApplicationEvents:

procedure TForm1.ApplicationEventslMessage(var Msg: tagMSG;

var Handled: Boolean);

begin

Handled := Editi.Focused and (Msg.Message=wm_Char)

and (Msg.wParam>=48) and (Msg.wParam<=57) end;

Если теперь запустить программу, ввод цифр в компонент Edit1 будет блокирован. В нашей простой программе есть единственный компонент, способный получать фокус ввода, поэтому проверка Editi. Focused в условном операторе является излишней. Я ввел ее только для того, чтобы продемонстрировать, как программа может определить получателя клавиатурного ввода.

Любая форма может иметь сколько угодно компонентов TAppicationEvents. Одно и то же сообщение поступает последовательно в каждый из них до тех пор, пока это сообщение не будет обработано или пока оно не поступит всем. Порядок получения сообщений обратен порядку размещения компонентов на форме: вначале сообщение получит последний размещенный на форме компонент, затем предпоследний и т. д. Этот порядок можно изменить с помощью метода Activate. Запретить получение остальным компонентам уже обработанного сообщения можно с помощью метода CancelDispatch. если в проекте имеется несколько форм, расположенные на них компоненты TAplicationEvents начинают получать сообщения только после того, как соответствующая форма станет активной. Работа всех компонентов TApplicationEvents будет блокирована, если в объекте Application определен обработчик события onMessage.

В Инспекторе объектов опубликованы только два свойства компонента: Name И Tag. Методы компонента:

procedure Activate; | Делает компонент первым получателем сообщения
procedure CancelDispatch; | Запрещает получение текущего сообщения остальным компонентам
События:

type TActionEvent = procedure (Action: TBasicAction; var Han dled: Boolean) of objects; property OnActionExecute: TActionEvent; | Это событие возникает тогда, когда пользователь активизирует управляющий элемент, приписанный определенному действию, в котором не определен обработчик OnExecute
type TActionEvent = procedure (Action: TBasicAction; var Han dled: Boolean) of object; property OnActionUpdate: TAction Event; | Это событие возникает тогда, когда пользователь активизирует управляющий элемент, приписанный определенному действию, в котором не определен обработчик OnUpdate
property OnActivate: TNotifyEvent; | Возникает при активизации приложения
property OnDeactivate: TNoti fyEvent; | Возникает при детивизации приложения
type TExceptionEvent = procedure (Sender: TObject; E: Exception) of object; property OnException: TException Event; | Возникает перед умалчиваемой обработкой исключения, для которого нет соответствующего программного обработчика.
type THelpEvent = function (Command: Word; Data: Longint; var CallHelp: Boolean): Boolean of object/ property OnHelp: THelpEvent; | Возникает перед вызовом встроенной справочной службы. Параметру CallHelp следует придать значение True, если программа должна после завершения обработчика вызвать справочную службу
property OnHint: TNotifyEvent; | Возникает перед выдачей оперативной справки для компонента, свойство Hint которого не пустая строка
type TIdleEvent = procedure (Sender: TObject; var Done: Boo lean) of object; | Возникает, когда программа переходит, в состояние ожидания. Если в Done установлено значение False, после выполнения
property Orrldle: TIdleEvent; | других работ Windows вновь вызывает приостановленную программу, в противно случае вызов программы происходит только при поступлении в ее адрес очередного сообщения
type TMessageEvent = procedure (var Msg: TMsg; var Handled: Boolean) of object; property OnMessage: TMessageEvent; | Возникает при поступлении любого сообщения от Windows. Msg - сообщение (его тип описан в п. 16.6.3), Handled=True, если обработчик завершил обработку сообщени
property OnMinimize: TNotifyEvent; | Возникает при минимизации главного окна программы
property OnRestore: TNotifyEvent; | Возникает при восстановлении размеров главного окна программы
ShortCutEvent = procedure (var Msg: TWMKey; var Handled: Boo lean) of object; property OnShortCut: TShortCutEvent; | Возникает, когда пользователь нажал клавишу на клавиатуре (перед событиями ОnKeyDown или OnKeyPress). Позволяет программе распознать и интерпретировать нажатие клавиш-акселераторов
type TShowHintEvent = procedure (var HintStr: String; var CanShow: Boolean; var Hintlnfo: THintInfo) of object- property OnShowHint: TShowHintEvent; | Возникает перед появлением оперативной справки Hint. HintStr - строка для справки; Hintlnfo - информация об окне справки. Установите в CanShow значение True, если нужно отобразить справку (остальные параметры к этому времени могут быть изменены)

18.2.15. TValueListEditor - специализированный редактор строк

Этот компонент введен в версии 6 и предназначен для редактирования списков строк вида имя=значение. Такие списки широко используются в реестре Windows и файлах инициализации. Наконец. начиная с версии 5 Delphi по умолчанию в таком формате хранит файлы описания форм dfm. Если на пустую форму положить компонент TValueListEditor, диалог TOpenDialog и кнопку TBitBtn, то после загрузки в редактор файла Example. dfm (для учебной формы, описанной в гл. 5) получим экран, показанный на рис. 18.17. Обработчик нажатия кнопки имеет такой вид:

procedure TFormI.BitBtnIClick(Sender: TObject);

begin

if OpenDialogI.Execute then

ValueListEditorl.Strings.LoadFromFile(

OpenDialogI.FileName)

end;

Непосредственным предком компонента является класс TCustomDrawGrid, поэтому многие его свойства, методы и события совпадают с описанными в п. 18.2.4 свойствами, методами и событиями компонента TStringGrid.

Специфичные свойства компонента:

property Cells[ACol, ARow: Integer]: String; | Открывает доступ к содержимому ячейки, лежащей на пересечении столбца ACol со строкой arow (нумерация столбцов и строк начинается с нуля)
property ColCount: Integer; | Содержит количество столбцов
type TDisplayOption = (doColumnTitles, doAutoColResize, doKeyColFixed) ; TDisplayOptions = set of TDisplayOption; property DisplayOptions: TDisplayOptions; | Свойство может включать следующие значения: doColumnTitles - первая строка содержит заголовки столбцов, определенные свойством TitleCaption, И не скроллируется; doAutoColResize - предписывает автоматически изменять ширину столбцов при изменении размеров компонента; doKeyColFixed - если указано, ширина первого столбца, содержащего имена, не меняется при изменении размеров

Рис. 18.17. Демонстрация компонента TValueListEditor

property DropDownRows: Integer; | Указывает максимальное количество строк в списке возможных значении, показ которых не сопровождается появлением полосы прокрутки
property ItemProps[const KeyOrIndex: Variant]: TItemProp; | Сложное свойство, управляющее различными аспектами отображения значений (см. пояснения ниже)
type TKeyOption = (keyEdit, keyAdd, keyDelete, keyUnique) ; TKeyOptions = set of TDisplayOption; property KeyOptions: TKeyOptions; | Управляет возможным изменением списка: keyEdit - пользователь может изменять имя параметра (в первом столбце); keyAdd - пользователь может добавлять новую пару имя-значение нажатием клавиши Insert (требует включения keyEdit); keyDelete -пользователь может уничтожить выделен ную пару нажатием клавиши Delete; keyUnique - названия вводимых пользователем имен должны быть уникальными
property Keys[Index: Integer]:String; | Открывает доступ к названиям значений по их индексам
property RowCount: Integer; | Содержит количество строк
property Strings: TStrings; | Содержит строки списка
property TitleCaptions: TStrings; | Содержит заголовки столбцов
property Values[const Key:String]: String; | Открывает доступ к значениям по их индексам

Свойство itemprops класса Titemprop имеет собственные свойства:

property EditMask: String; | Содержит маску для формирования значения. Правила создания маски описаны в п. 18.2.3
type TEditStyle = (esSimple, esEllipsis, esPickList); property EditStyle: TEditStyle; | Определяет правила редактирования значения: esSimple - значение редактируется в обычном однострочном редакторе; esEllipsis - в строку значения вставляется кнопка для вызова диалогового окна редактора значения (возбуждается событие OEditButtonclick); esPickList - в строку значения вставляется кнопка для раскрытия списка возможных значений (возбуждается событие OnGetPickList)
property MaxLength: Integer; | Определяет максимальную длину (в символах) значения. Если 0, нет ограничений на длину
property PickList: TStrings; | Содержит выпадающий список возможных значений
property Readonly: Boolean; | Разрешает/запрещает редактирование значения

Свойство PickList не предназначено для программного доступа. Чтобы создать выпадающий список возможных значений, нужно свойству ItemProp.EditStyle присвоить значение esPickList и написать обработчик события onGetpickList. Пусть, например, первое значение должно иметь выпадающий список. Тогда необходим такой код:

procedure TFormI.FormActivate(Sender: TObject);

begin

ValueListEditorl.ItemProps[1].EditStyle := esPickList;

end;

procedure TFormI.ValueListEditorlGetPickList(Sender: TObject;

const KeyName: String; Values: TStrings);

begin

// Содержимое списка доступно через параметр Values:

Values.Add('1') ;

Values.Add('2') ;

Values.Add ('3') ;

Values.Add('4') ;

end;

Следующие свойства компонента аналогичны одноименным

Свойствам компонента TStringGrid (cm. П. 18.2.4): BorderStyle, Col, ColWidths, DefaultColWidth, DefaultDrawing, DefaultRowHeight, EditorMode, FixedColor, FixedCols, GridHeight, GridLineWidth, GridWidth, LeftCol, Options, Row, RowHeights, ScrollBars, Selection, TabStops, TopRow, VisibleColCount,VisibleRowCount. function InsertRow(const KeyName,. "."alue: String; Append: Boolean) : Integer-procedure Refresh; function RestoreCurrentRow: Boolean;

Методы CellRect, MouseToCell И MouseCoord аналогичны одноименным методам компонента TStringGrid (см. п. 18.2.4). События компонента:

property OnEditButtonClick: TNo tifyEvent; | Возникает при щелчке по кнопке раскрытия диалогового окна редактирования значения. Свойство ItemProps .EditStyle должно содержать значение esEllipse
type TGetPickListEvent = proce dure (Sender: TObject; const KeyName: String; Values: TStrings) of object; property OnGetPickList: TGetPick ListEvent; | Возникает при щелчке по кнопке раскрытия списка возможных значений. Параметр KeyName содержит имя строки, в которой произведен щелчок. Обработчик должен заполнить возможными значениями список Values. Свойство ItemProps. EditStyle должно содержать значение esPickList
property OnStringsChange: TNotifyEvent; | Возникает сразу после изменения имени или значения текущей строки
property OnStringsChanging: TNotifyEvent; | Возникает непосредственно перед изменением имени или значения текущей строки
type TOnValidateEvent = procedure (Sender: TObjectACol, ARow: Longint; const KeyName, KeyValue:String) of object; property OnValidate: TOnValidateEvent; | Возникает перед тем как фокус ввода покинет ячейку ACol, ARow. Обработчик может проверить новые значения KeyName и KeyValue и возбудить исключение, если исправления в строке были ошибочными

Следующие события аналогичны одноименным событиям компонента TStringGrid: OnDrawCell, OnGetEditMask, OnGetEditText OnRowMoved, OnSelectCell, OnSetEditText, OnTopLeftChanged.

18.2.16. TLabelEdit - однострочный редактор с меткой

Представляет собой удобную комбинацию однострочного редактора с меткой. Надпись в метке определяет свойство EditLabei. Свойство

type TLabelPosition = (IpAbove, ipBelow, IpLeft, IpRight);

property LabelPosition: TLabelPosition;

определяет положение метки относительно редактора, а

property LabelSpacing: Integer;

расстояние от метки до редактора (в пикселях). Впервые введен в версии 6.

18.2.17. TColorBox - список выбора цвета

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

TColorGrid (страница Samples) и TColorDialog (страница Dialogs) состав отображаемых им цветов может меняться.

Многие свойства, методы и события компонента совпадают с одноименными свойствами, методами и событиями его ближайшего родственника - компонента TCоmbоВох (см. п. 18.1.10).

Специфичные свойства компонента:

property ColorNames[Index: Inte ger]: Strings; | Возвращает имя цвета по его индексу в списке выбора
property Colors[Index: Integer]: TColor; | Содержит список цветов
property DefaultColorColor: TColor; | Указывает умалчиваемый цвет. Свойство Style должно включать флаги cbSystem Colors И cbIncludeDefault
property NoneColorColor: TColor; | Указывает цвет “нет цвета”. Свойство Style должно включать флаги cbSystem Colors и cbIncludeNone
property Selected: TColor; | Указывает текущий выбранный цвет
type TColorBoxStyles = (cbStandardColors, cbExtendedColors, cbSystemColors, cblnclude None, cbIncludeDefault, cbCustomColor, cbPrettyNames); TColorBoxStyle = set of TColor BoxStyles; property Style: TColorBoxStyle | Определяет отображаемые компонентом цвета: cbStandardColors - список содержит 16 основных цветов; cbExtendedColors -список содержит дополнительные цвета, определенные в модуле Graghics; cbSystemColors - в списке отображаются цвета cIMoneyGreen,cISkyBlue,cICream и cIMedGray; cbIncludeNone -список содержит опцию cINone;cbIncludeDefault -список содержит опцию cIDefault; cbCus tomcolor - первая опция списка открывает стандартный диалог TColorDialog; cbPrettyNames - имена цветов отображаются без префикса cl

18.2.18. TChart - построитель графиков

Этот компонент предназначен для графического представления числовых данных. На рис. 18.18 показан пример использования компонента.

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

Общая схема его использования такова.

Вначале компонент помещается на форму. После щелчка по нему правой кнопкой мыши вызывается его вспомогательное меню, которое в числе прочих содержит опцию Edit chart - с помощью этой опции вызывается многолистное окно редактора компонента. Закладка Series этого окна открывает доступ к так называемым сериям - объектам класса TChartSeries, которые, собственно, и будут отображать наборы чисел в графическом виде. Чтобы отобразить данные, нужно создать как минимум одну серию - для этого следует в окне редактора нажать кнопку Add и выбрать подходящий тип графика (рис. 18.19).

После закрытия редактора компонент будет содержать примерный вид графика. Однако его реальный вид зависит от фактических данных, которые создаются в работающей программе и добавляются к серии с помощью методов AddX, AddY или AddXY объекта TChartSeries (получить доступ к нужной серии можно с помощью индексированного свойстваSeriesList - первая созданная серия имеет индекс 0, вторая 1 и т. д.). Например, такой обработчик события OnActivate формы создал график, показанный на рис. 18.18:

procedure TForm1.FormActivate(Sender: TObject);

var

k: Integer;

begin

for k := 0 to 20 do

Chartl.SeriesList[0].AddXY(k,sin(k*pi/10),' ',clRed) ;

end;

Рис. 18.18. Пример использования компонента Tchart

Рис. 18.19. Возможные виды графиков компонента TChart

Компонент впервые появился в версии 3.

18.2.19. TActionManager - менеджер действий

Вместе с тремя другими компонентами страницы Additional -

TActionMainMenuBar, TActionToolBar И TCustomDIg (все перечислен ные компоненты впервые введены в версии 6) позволяет создавать настраиваемый пользовательский интерфейс.

Таким интерфейсом обладает, например, среда Delphi: вы можете добавить/удалить любую инструментальную кнопку, запретить/разрешить выбор кнопок и опций меню и т. п.

Компонент TActionManager централизует однотипные действия, производимые схожими в функциональном отношении элементами интерфейса. Каждое такое действие компонент сохраняет в дисковом файле, что позволяет программе “запоминать” последние настройки, произведенные пользователем. Таким образом, компонент значительно расширяет функциональность компонента TActionList (см. п. 18.1.16) и по существу делает его ненужным.

Компонент оперирует категориями однотипных действий (Edit, File, Format и т. п.) и может размещать категории в контейнере тасtionMainMenuBar (в виде опций меню), а входящие в них действия - в контейнере TActionToolBar (в виде инструментальных кнопок). В

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

Познакомимся с методикой использования компонента на следующем примере.

- Поместите на пустую форму компоненты TActionManager, ТАсtionMainMenuBar, TActionToolBar И TCustomizeDlg. по умолча-нию контейнеры TActionMainMenuBar И TActionToolBar займут верхнюю часть формы, положение двух других компонентов не имеет значения.
- Дважды щелкните по компоненту или вызовите его локальное меню и выберите опцию customize - на экране появится окно редактора компонента (рис. 18.20).

Рис. 18.20. Редактор компонента TActionManager

- Щелкните по окну правой кнопкой и выберите New Standard Action или просто нажмите Ctrl+Ins - на экране появится дополнительное окно с перечнем всех определенных в Delphi стандартных классов действий (рис. 18.21).
- С помощью полосы скроллирования сместите список вверх и выберите в нем все классы, связанные с категорией File (для выбора нескольких классов одновременно щелкайте по каждому, удерживая нажатой клавишу Ctrl).
- “Схватите” мышью категорию File и перетащите ее на полосу TActionMainMenuBar. Раскройте категорию и перетащите на полосу TActionToolBar опцию Exit.
- Поместите в свойство/событие ActionManager компонента TCustomizeDIg ссылку на компонент ActionManagerl.
- Напишите такой обработчик onciick для полосы TActionToolBar:

procedure TFormI.ActionToolBarlClick(Sender: TObject);

begin

CustomizeDlgl.Show

end;

Рис. 18.21. Окно со списком стандартных действий

Если вы запустите программу, то увидите пустое окно с меню File и инструментальной кнопкой Exit, причем опции меню (кроме недоступной опции Run) и инструментальная кнопка выполняют ожидаемые от них действия. Щелчок по инструментальной панели активизирует уже знакомое нам (рис. 18.20) окно редактора Atcion-Manageri, и вы можете изменять состав меню и инструментальной панели.

Свойства компонента:

property ActionBars: TAction Bars; | Содержит коллекцию всех инструменталь ных полос, определенных в приложении. Коллекция автоматически пополняется, когда на очередную полосу впервые кладется элемент меню (категория) или кнопка (действие)
property ActionCount: Integer; | Содержит общее количество определенных в программе действий
property Actions[Index: Integer]: TContainedAction; | Открывает индексированный доступ к конкретному действию
property FileName: TFileName; | Имя файла, в котором компонент сохраняет текущую конфигурацию действий
property LinkedActionLists: TActionListCollection; | Содержит коллекцию всех связанных с компонентом действий
property Images: TCustomImageList; | Ссылка на связанное с компонентом хранилище изображений
property PrioritySchedule: TStringList; | Содержит для каждого действия номера сессий (запусков программы), когда связанная с действием кнопка или опция меню меняла свою видимость. Если какой-то элемент интерфейса должен постоянно присутствовать на экране, его строка PrioritySchedule должна хранить (-1)
type TActionListState = (asNormal, asSuspended, asSuspendedEnabled) ; | Включает или отключает действия: asNormal - все действия включены; asSuspended - все действия выключены, их свойства
property State: TActionListState; | Enabled не изменяются; asSuspendedE nabled - все действия выключены, их свойства Enabled получают значения True

Если свойство FileName не определено, компонент не сможет запоминать изменения, сделанные пользователем в интерфейсе программы, и представит элементы интерфейса так, как они были определены при создании программы. Для файла нет умалчиваемого расширения, но сама среда Delphi запоминает сделанные вами изменения в файле BIN\DELPHI32 . DMT.

Методы компонента:

procedure LoadFromFile(const FileName: String); | Читает файл, указанный в параметре File-Name и загружает информацию, необходимую для восстановления полос действий
procedure LoadFromStream(Stream: TStream); | Загружает информацию, необходимую для восстановления полос действий, из потока Stream Восстанавливает вид полосы таким, как сохраняет ее свойство DefaultActionBar Уничтожает файл, указанный в свойстве FileName
procedure ResetActionBar(Index: Integer) ; procedure ResetUseageData; | Сохраняет текущие настройки интерфейса в файле FileName
procedure SaveToFile(const FileName: String) ; procedure SaveToStream(Stream: TStream); | Сохраняет текущие настройки интерфейса в потоке Stream
function ExecuteAction(Action: TBasicAction): Boolean; override; | Создает событие OnExecute для выполнения действия Action

18.2.20. TActionMainMenuBar - полоса меню для действий

Компонент служит настраиваемым контейнером для размещения связанных с действиями опций меню. Опции-заголовки размещаются “перетаскиванием” из окна менеджера действий (рис. 18.20) категорий.

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

property ActionClient: TActionClient;

Свойство visible класса TActionClient управляет видимостью полосы. Для компонента TActionMainMenuBar (в отличае от TActionToolBar) это свойство не может иметь значение False (независимо от количества компонентов на форме). Иными словами, программа не может “спрятать” полосы главного меню.

18.2.21. TActionTollBar - полоса кнопок для действий

Компонент служит настраиваемым контейнером для связанных с действиями инструментальных кнопок. Кнопки реализуются техникой “перетаскивания” действий из окна менеджера действий (рис. 18.20).

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

18.2.22. TCustomizeDIg - диалог настройки интерфейса

Этот компонент служит для активизации окна менеджера действий (рис. 18.20). Для этого у него имеется единственный метод

procedure Show;

Свойство

property ActionManager: TCustomActionManager;

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

property StayOnTop: Boolean;

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

Для вызова метода show проще всего использовать дополнительное меню контейнера опций или кнопок. Например:

procedure TFormI.NIClick(Sender: TObject);

begin

CustomizeDlgl.Show

end;