4.6.5.6 TDBImage

Создает, по аналогии с компонентой

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

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

DataSource. Свойство DataField содержит поле в наборе данных, к которому вы хотите обратиться.

Свойство

AutoDisplay управляет автоматическим масштабированием контейнера. Чтобы исходное изображение меньшего размера растянулось на весь контейнер, установите значение true свойства Stretch. Если вы передумали и хотите вернуть изображение в исходное состояние, нажмите клавишу Esc - конечно, до того, как перейти к другой записи. Во время выполнения программы вы можете вырезать, копировать и восстанавливать изображение из базы данных, нажимая типовые комбинации клавиш (Ctrl+X, Ctrl+C и Ctrl+V).

4.6.5.7 TDBListBox

Создает, по аналогии с компонентой

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

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

DataSource. Свойство DataField содержит поле в наборе данных, к которому вы хотите обратиться.

Элементы списка, которые может выбирать пользователь, содержатся в свойстве

Items, а номер выбранного элемента - в свойстве Itemlndex. Вы можете динамически добавлять, вычеркивать и вставлять элементы списка с помощью методов Add, Append, Delete и Insert объекта Items, например:

DBListBoxl->Items.Delete(3);

4.6.5.8 TDBComboBox

Создает, по аналогии с компонентой

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

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

DataSource. Свойство DataField содержит поле в наборе данных, к которому вы хотите обратиться.

Элементы списка, которые может выбирать пользователь, содержатся в свойстве

Items, номер выбранного элемента - в свойстве Itemlndex, а сам выбранный текст - в свойстве SelText. Свойства SelStart и SelLength позволяют установить выборку части текста или обнаружить, какая часть текста выбрана. Вы можете динамически добавлять, вычеркивать и вставлять элементы списка с помощью методов Add, Append, Delete и Insert объекта Items, например:

DBComboBoxl->Items->Insert

(4, "Пятый элемент списка");

Правила сортировки списка задаются свойством

Sorted. Вид и поведение компоненты TDBComboBox можно выбрать в свойстве Style.

4.6.5.9 TDBCheckBox

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

TCheckBox чек-бокс выбора состояния, связанного с конкретной записью в наборе данных.

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

DataSource. Свойство DataField содержит поле в наборе данных, к которому вы хотите обратиться.

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

ValueChecked, бокс переходит в начальное состояние "checked". Если содержимое поля текущей записи совпадает со значением свойства ValueUnchecked, бокс переходит в начальное состояние "unchecked". В зависимости от установленного пользователем состояния бокса, текущая запись приобретает значение свойства ValueChecked или ValueUnchecked, при условии, что свойство Readonly имеет значение false и набор данных находится в режиме редактирования. Если вы хотите запретить пользователю изменять поля записей, установите значение true свойства ReadOnly.

4.6.5.10 TDBRadioGroup

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

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

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

Values: первой строке Values соответствует первая строка свойства Items и т.д.

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

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

DataSource. Свойство DataField содержит поле в наборе данных, к которому вы хотите обратиться.

Добавление кнопок к компоненте

TDBRadioGroup выполняется редактированием свойства Items. Присвоение названия очередной строке свойства Items приводит к появлению этой кнопки в группирующей рамке. Значение свойства Itemlndex определяет, какая радио-кнопка выбрана в настоящий момент. Вы можете группировать радио-кнопки в несколько столбцов, устанавливая соответствующее значение свойства Columns.

4.6.5.11 TDBLookupListBox

Создает таблицу ссылок для заполнения полей информацией из другого набора данных.

Небольшая по объему таблица ссылок

(lookup table) содержит коды разрешенных значений, которые может принимать некоторое поле. Например, в базе данных электронной записной книжки обязательно имеются записи почтовых адресов. Название города и улицы из конкретного адреса можно закодировать в таблицах ссылок "Города" и "Улицы". Компоненты будут эффективно обращаться с короткими кодами полей (например, "МК" вместо "Москва" или "ЛНП" вместо "Ленинградский проспект"), структура базы данных станет равномерной, а пользователь по-прежнему будет оперировать с полями полных названий.

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

TDataSource, который идентифицируется значением свойства DataSource. Свойство DataField указывает либо на поле в наборе данных, либо на поле в таблице ссылок, к которому вы хотите обратиться. В последнем случае вам не надо определять прочие свойства - компонента сделает это самостоятельно.

Не забудьте поместить на форму еще пару компонент

TTable и TDataSource, чтобы получать информацию из таблицы ссылок. Свойство ListSource идентифицирует источник таблицы ссылок. Свойство ListField представляет поле в таблице ссылок, содержащее код ссылки как таковой. Свойство KeyField определяет индекс поля ссылки, которое вы хотите скопировать в DataField.

4.6.5.12 TDBLookupComboBox

Создает комбинацию области редактирования и выпадающей таблицы ссылок для заполнения полей информацией из другого набора. Смысловое содержание свойств компонент TDBLookupComboBox и

TDBLookupListBox полностью совпадает.

4.6.6 Компоненты

Win 3.1

Компоненты вкладки

Win 3.1 палитры компонент

представляют 7 интерфейсных элементов

Windows 3.1 для включения в вашу программу.

4.6.6.1 TDBLookupList

Эта компонента поддерживает совместимость с системой

Windows 3.1; ее аналогом является компонента TDBLookupListBox из вкладки Data Controls.

4.6.6.2 TDBLookupCombo

Эта компонента поддерживает совместимость с системой

Windows 3.1; ее аналогом является компонента TDBLookupComboBox из вкладки Data Controls.

4.6.6.3 [TTabSet

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

Windows 3.1; ее аналогом является компонента TTabControl из вкладки Win95.

Названиявкладок вводятся в список свойства

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

TabSetl->Tabs = Notebookl->Pages;

Notebookl->PageIndex = TabSetl->TabIndex;

Номер выбранной вкладки содержится в свойстве

Tablndex. Чтобы определить, какая вкладка является (или сделать вкладку) первой видимой в наборе, воспользуйтесь свойством Firstlndex.

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

alBottom свойства Align требует разместить вкладки внизу формы. Цветовое различие выбранной и невыбранных вкладок задают свойства SelectedColor и UnselectedColor. Свойства BackgroundColor и DitherBackground меняют цвет и яркость фона под набором вкладок. Расстояние вкладок от краев компоненты определяют свойства StartMargin и EndMargin. Чтобы появлялись кнопки прокрутки, когда не хватает места для отображения всех вкладок, установите значение true свойства AutoScroll. Выбор между надписями и графическими изображениями на вкладках осуществляет свойство Style.

4.6.6.4 TOutline

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

Отрезки линий обводки (ветви дерева) пронумерованы, начиная с 1, и содержатся в массиве свойства

Items. Одна и та же, например, первая (верхняя) ветвь некоторого дерева Outlinel может адресоваться прямо, как Outlinel[l], или косвенно, как Outlinel. Items[l]. Дерево имеет смысл строить во время выполнения программы. Добавляйте новые родительские ветви к дереву с помощью методов Add и AddObject. Добавляйте новые ветви потомков с помощью методов AddChild и AddChildObject. Для замены существующей ветви используйте методы Insert и InserObject. Метод Delete вычеркивает указанную ветвь.

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

BeginUpdate и EndUpdate, что избавит от избыточной перенумерации ветвей в процессе создания дерева. Значение свойства Selectedltem отражает номер текущей выбранной ветви.

Узлы дерева могут сопровождаться идентифицирующими картинками. Свойство

OutlineStyle определяет очертание дерева и тип узловых картинок, а их вид конкретизируют свойства PictureLeaf, PictureMinus, PicturePlus, PictureOpen и PictureClosed.

4.6.6.5 THeader

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

Windows 3.1; ее аналогом является компонента THeaderControl из вкладки Win95.

Секции заголовка содержатся в свойстве

Sections. Можно изменять размер выбранной секции и перетаскивать ее границы в новое положение, удерживая нажатой кнопку мыши: на стадии проектирования - правую кнопку, а во время выполнения программы - левую. Размеры других секций остаются без изменения.

Если свойство

AllowResize разрешает изменение размера, то в начале изменения происходит событие OnSizing, а по окончании изменения - событие OnSized. Обработчики этих событий могут, например, выровнять текст под заголовком в соответствии с новой шириной секции.

4.6.6.6 TTabbedNotebook

Представляет ряд страниц блокнота, каждая из которых содержит собственный набор элементов управления. Нажимая на закладку, которая выступает из верхней части страницы, пользователь выбирает ее. Эта компонента поддерживает совместимость с Windows 3.1; ее аналогом является компонента TPageControl из вкладки Win95.

Доступные страницы блокнота с закладками представляют собой символьные последовательности, перечисленные как значения свойства Pages. Окно редактора блокнота (Рис. 4.20) открывается кнопкой в графе значений этого свойства. Вы можете активизировать конкретную страницу одним из следующих способов: выбрав ее из выпадающего списка свойства ActivePage, a также перелистывая закладки с помощью опций Next Page и Previous Page контекстного меню.

Рис. 4.20. Конструирование заготовки блокнота.

Если вы хотите переопределить значение указателя Pagelndex для конкретной страницы, обратитесь к методу GetIndexForPage. Свойство TabsPerRow определяет число закладок в одном ряду. Если в блокноте имеется больше страниц, чем закладок, умещающихся в ряду, автоматически достраивается следующий ряд закладок. Шрифт надписей на закладках задается свойством TabFont.

4.6.6.7 TNotebook

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

Доступные страницы блокнота представляют собой символьные последовательности, перечисленные как значения свойства Pages. Обратиться к конкретной странице блокнота можно посредством свойств Pagelndex или ActivePage.

4.6.7 Диалоговые компоненты

Компоненты вкладки Dialogs палитры компонент

осуществляют включение в вашу программу 8 диалоговых элементов Windows, являющихся прямыми производными от абстрактного класса TCommonDialog.

4.6.7.1 TOpenDialog

Открывает в вашей программе доступ к диалогу открытия файлов. Метод Execute активизирует окно диалога во время выполнения программы.

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

Манипулируя свойством Options, вы можете изменить вид и поведение компоненты, например, разрешить выборку нескольких файлов одновременно; имена этих файлов сохранятся в списке свойства Files. Если вы хотите, чтобы расширения автоматически приписывались к именам файлов, печатаемых в области редактируемого ввода, используйте свойство DefaultExt.

4.6.7.2 TSaveDialog

Открывает в вашей программе доступ к диалогу сохранения файлов. Метод Execute активизирует окно диалога во время выполнения программы.

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

Манипулируя свойством Options, вы можете изменить вид и поведение компоненты. например, разрешить выборку нескольких файлов одновременно; имена этих файлов сохранятся в списке свойства Files. Если вы хотите, чтобы расширения автоматически приписывались к именам файлов, печатаемых в области редактируемого ввода, используйте свойство DefaultExt.

4.6.7.3 TFontDialog

Открывает в вашей программе доступ к диалогу выбора шрифтов и их атрибутов. Execute активизирует окно диалога во время выполнения программы.

После того, как пользователь выбрал нужный шрифт и нажал кнопку ОК, выбранный шрифт заносится в свойство Font. Свойство Device позволяет выбрать устройство, на которое повлияет сделанное изменение шрифта.

Манипулируя свойством Options, вы можете изменить вид и поведение компоненты, например, включить кнопку Help в окно диалога или разрешить появление в списке только шрифтовых файлов с расширением .ttf(True Type Fonts).

4.6.7.4 TColorDialog

Открывает в вашей программе доступ к диалогу выбора цветов. Метод Execute активизирует окно диалога во время выполнения программы.

После того, как пользователь выбрал нужный цвет и нажал кнопку ОК, диалог закрывается, и выбранный цвет заносится в свойство Color.

4.6.7.5 TPrintDialog

Открывает в вашей программе доступ к диалогу печати. Метод Execute активизирует окно диалога во время выполнения программы.

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

При нажатии на кнопку Setup происходит вызов диалога установок принтера (TPrinterSetupDialog). Манипулируя свойством Options, вы можете изменить вид и поведение компоненты, например, отменить появление опции печати в файл.

4.6.7.6 TPrinterSetupDialog

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

4.6.7.7 TFindDialog

Открывает в вашей программе доступ к диалогу поиска текста. Метод Execute активизирует окно диалога во время выполнения программы.

Значением свойства FindText является искомый текст. Манипулируя свойством Options, вы можете изменить вид и поведение компоненты, например, отменить появление встроенных компонент TCheckBox под названиями Match Case, Whole Word и др.

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

4.6.7.8 TReplaceDialog

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

4.6.7.9 Использование диалоговых компонент текстовым редактором. Приемы отладки

C++Builder поставляется вместе с примером текстового редактора файлов формата RTF. который демонстрирует работу диалоговых компонент TOpenDialog, TSaveDialog, TFontDialog и TPrintDialog. Приложение также использует ранее описанные компоненты TMainMenu, TRichEdit, TPanel, TEdit, TSpeedButton. TComboBox, TUpDown, TLabel, TBevel и способно предоставлять контекстно-зависимую помощь из файла RICHEDIT.HLP.

=> По команде главного меню File | Open Project откройте диалог выбора проектов.

=> Войдите в каталог \...\CBuilder\Examples\Apps\RichEdit.

=> Выберите проектный файл с именем RichEdit и нажмите кнопку Open.

Рис. 4.21. Форма текстового редактора.

Рис. 4.21 показывает главную форму текстового редактора с перечнем имен основных обработчиков событий, коды которых, как правило, и составляют содержание файлов программных модулей приложений для C++Builder.

Компонента TRichEdit занимает всю свободную область формы редактора, причем вложенные свойства RichEditl->Paragraph содержат атрибуты форматирования параграфов документа. Объект FontName представляет название шрифта, выбранное пользователем из выпадающего списка TComboBox. Для установки размера шрифта служит объект FontSize области редактируемого ввода TEdit, сопряженный с кнопками TUpDown. Под панелью инструментов рас-

положена измерительная линейка с тремя регуляторами форматирования (объекты типа TLabel): левого отступа параграфа Leftind, ширины красной строки Firstind и правого отступа параграфа Rightind (последний регулятор появится после запуска программы). Внизу формы расположена панель строки состояния StatusBar, предназначенная для вывода пояснений к командам меню.

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

File | Edit | Help
New Open Save Save As |  | Undo |  | Contents Search for Help On How to Use Help
Cut Copy Paste
About
Print | Font |
Exit |

Вы можете отредактировать (например, с помощью того же Microsoft Word) исходный справочный файл RICHEDIT.RTF из каталога \...\CBuilder\Examples\Apps\RichEdit\Help, а затем собрать новую версию RICHEDIT.HLP с помощью утилиты BUILDHLP.BAT. Наличие действующей команды меню Help придает программе профессиональный облик и облегчает работу пользователя.

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

ttinclude <vcl.h> ttinclude <windows.hpp> ftpragma hdrstop

#include "Romain.h"

^include "RichAbt.h"

const float RulerAdj = 4.0/3.0; // цена деления линейки

const int GutterWid = 6; // ширина поля подшивки

//-----_-------________--________--________--_____-__--_____

#pragma resource "*.dfm" TMainForm *MainForm;

// Конструктор главной формы приложения _fastcall TMainForm::TMainForm(TComponent *0wner)

: TFormfOwner) { SetFileName((AnsiString)"Untitled") ;

)

// Установка текущих атрибутов Форматирования текста void _fastcall TMainForm::SelectionChange(TObject*) { char sizebuf[6];

try { FUpdating = true;

FirstInd->Left = // левая граница красной строки int(RichEditl->Paragraph->FirstIndent*RulerAdj)-

4+GutterWid;

LeftInd->Left = // левый отступ параграфа int((RichEditl->Paragraph->LeftIndent+

RichEditl->Paragraph->FirstIndent)*RulerAdj)-

4+GutterWid;

RightInd->Le?t = II правый отступ параграфа •" Ruler->ClientWidth-6-

int((RichEditl->Paragraph->RightIndent+GutterWid)*

RulerAdj) ;

BoldButton->Down = // состояние кнопки "жирный" RichEditl->SelAttributes->Style.Contains(fsBold) ;

ItalicButton->Down = //состояние кнопки "курсив" RichEditl->SelAttributes->Style.Contains(fsltalic) ;

UnderlineButton->Down = // состояние кнопки "подчерк." RichEditl->SelAttributes->Style.Contains(fsUnderline) ;

BulletsButton->Down = // состояние кнопки "нумерация" bool(RichEditl->Paragraph->Numbering) ;

FontSize->Text = // размер шрифта itoa(RichEditl->SelAttributes->Size, sizebuf, 10);

FontName->Text = // название шрифта RichEditl->SelAttributes->Name;

// Состояние кнопок выравнивания параграфа switch((int)RichEditl->Paragraph->Alignment) { case 0: LeftAlign->Down = true; break;

case 1: RightAlign->Down = true; break;

case 2: CenterAlign->Down = true; break;

} }

catch (...)

{ FUpdating = false; } // ошибка (поймано исключение) FUpdating = false;

}

// функция возвращает установленные атрибуты текущего текста TTextAttributes *_fastcall TMainForm::CurrText(void) { return RichEditl->SelAttributes;

}

// функция добавляет указанный шрифт к списку имеющихся int EnumFontsProc(TLogFontA &LogFont, TTextMetricA &, int,

Pointer Data) { ((TStrings *)Data)->Add((AnsiString)LogFont.IfFaceName);

return 1;

}

// функция выбирает имена имеющихся шрифтов void _fastcall TMainForm::GetFontNames(void) { HDC hDC = GetDC(O) ;

void * cTmp = (void *)FontName->Items;

EnumFonts(hDC, NULL, (FONTENUMPROC) EnumFontsProc, (long) cTmp ) ;

ReleaseDC(0,hDC) ;

FontName->Sorted = true;

}

// Включение имени Файла в строку заголовка приложения void _fastcall TMainForm::SetFileName(const AnsiString

FileName) ( LPSTR IpBuf = new char[MAX_pATH];

sprintf(IpBuf, "%s-%s", ExtractFileName(FileName).c_str(), Application->Title.c_str()) ;

Caption = (AnsiString)IpBuf;

FFileName = FileName;

delete IpBuf;

}

// Реакция в диалоге "Сохранить изменения?" void _fastcall TMainForm::CheckFileSave(void) { if (RichEditl->Modified) {

switch(M&ssageBox(Handle, "Save Changes?", "Confimation",

MB_YESNOCANCEL I MB_ICONQUESTION)) { case ID_YES : FileSaveClick(this) ;

case ID_CANCEL : Abort() ;

};

) }

// Запись рисок измерительной линейки ширины параграфов void _fastcall TMainPorm::SetupRuler(void) { int iCtr = 1;

char sTmp[201] ;

while (iCtr < 200) (

sTmp[iCtr++] = 9; // табулятор sTmp[iCtr++] = 'I'; // риска } Ruler->Caption = (AnsiString)sTmp;

}

// Информирует Windows о текущем размере окна редактирования void _fastcall TMainForm::SetEditRect(void) ( TRect Ret = Rect(GutterWid, 0,

RichEditl->ClientWidth-GutterWid, ClientHeight) ;

SendMessage(RichEditl->Handle, EM_SETRECT, 0, long(&Rct));

}

// Инициализирует компонентные объекты формы приложения void _fastcall TMainForm::FormCreate(TObject* /*Sender*/) { Application->OnHint = &ShowHint;

OpenDialog->InitialDir = ExtractFilePath(ParamStr(0)) ;

SaveDialog->InitialDir = OpenDialog->InitialDir;

GetFontNames() ;

SetupRuler() ;

SelectionChange(this); // атрибуты форматирования

}

// Выдает пояснения к командам меню в строку состояния void_fastcall TMainForm::ShowHint(TObject* /*Sender*/) { StatusBar->SimpleText = Application->Hint;

}

// Создание пустого безымянного Файла по команде File I New void_fastcall TMainForm::FileNewClick(TObject* /*Sender*/) { CheckFileSavef); // сохранить изменения? SetFileName((AnsiString)"Untitled") ;

RichEditl->Lines->Clear() ;

RichEditl->Modified = false;

}

// Загрузка выбранного Файла командой File I Open или кнопкой void _fastcall TMainForm::FileOpenClick(TObject*) { CheckFileSave(); // сохранить изменения? if (OpenDialog->Execute()) {

RichEditl->Lines->LoadFromFile(OpenDialog->FileName) ;

SetFileName(OpenDialog->FileName) ;

RichEditl->SetFocus() ;

RichEditl->Modified = false;

RichEditl->ReadOnly =

OpenDialog->Options.Contains(ofReadOnly) ;

} }

// Запись Файла командой File I Save или кнопкой void?*_fastcall TMainForm::FileSaveClick(TObject* Sender) { if (!strcmp(FFileName.c_str(), "Untitled"))

FileSaveAsClick(Sender); // нет имени else

{ RichEditl->Lines->SaveToFile(FFileName); // то же имя RichEditl->Modified = false;

} )

// Запись Файла под выбранным именем командой FilelSaveAs void _fastcall TMainForm::FileSaveAsClick(TObject*) { if (SaveDialog->Execute()) {

RichEditl->Lines->SaveToFile(SaveDialog->FileName) ;

SetFileName(SaveDialog->FileName) ;

RichEditl->Modified = false;

} }

// Диалог печати Файла по команде File I Print или кнопкой void _fastcall TMainForm::FilePrintClick(TObject*) { if (PrintDialog->Execute()) RichEditl->Print( FFileName );

}

// Выход из программы по команде File I Exit void _fastcall TMainForm::FileExitClick(TObject*) { Close() ;

}

// Отмена редактирования командой Edit I Undo или кнопкой void _fastcall TMainForm::EditUndoClick(TObject*) ( if (RichEditl->HandleAllocated())

SendMessage(RichEditl->Handle, EM_UNDO, 0, 0) ;

}

// Вырезка выбранного текста командой Edit I Cut или кнопкой void _fastcall TMainForm::EditCutClick(TObject*) { RichEditl->CutToClipboard();

}

// Копирование текста командой Edit I Copy или кнопкой void _fastcall TMainForm::EditCopyClick(TObject*) { RichEditl->CopyToClipboard();

}

// Вставка текста командой Edit I Paste или кнопкой void _fastcall TMainForm::EditPasteClick(TObject*) { RichEditl->PasteFromClipboard() ;

}

// Вывод указателя Файла помощи по команде Help I Contents void _fastcall TMainForm::HelpContentsClick(TObject*) { Application->HelpCommand(HELP_CONTENTS, 0) ;

}

// Поиск заданной справки по команде Help I Search...

void _fastcall TMainForm::HelpSearchClick(TObject*)

{ Application->HelpCommand(HELP_PARTIALKEY, (long) "");

)

// Вывод оглавления Файла помощи по команде Help I Нои to... void _fastcall TMainForm::HelpHowToClick(TObject*) { Application->HelpCommand(HELP_HELPONHELP, 0) ;

}

// Диалог с логотипом редактора по команде Help I About

void_fastcall TMainForm::HelpAboutClick(TObject*)

{ Porm2 = new TPorm2(Application); // создать объект формы

Form2->ShowModal(); // активировать диалог

delete Porm2; // уничтожить объект }

// Диалог выбора шрифта и его атрибутов по команде Edit I font void _fastcall TMainPorm::SelectFont(TObject*) { FontDialogl->Font->Assign(RichEditl->SelAttributes);

if (FontDialogl->Execute())

CurrText()->Assign(FontDialogl->Font) ;

RichEditl->SetFocus() ;

}

// Адаптация длины линейки к текущему окну редактирования void _fastcall TMainForm::RulerResize(TObject*) { RulerLine->Width =

(int)Ruler->ClientWidth-(RulerLine->Left*2) ;

}

// Реакция на изменение пользователем размеров формы

void _fastcall TMainForm::FormResize(TObject* Sender)

{ SetEditRect(); // послать сообщение Windows

SelectionChange(Sender); // атрибуты форматирования

)

// Перерисовка формы

void _fastcall TMainForm::FormPaint(TObject* Sender) { SetEditRect(); // послать сообщение Windows

}

// Реакция на нажатие кнопки "Стиль шрифта жирный" void _fastcall TMainForm::BoldButtonClick(TObject*) { if (iFUpdating)

{ if (BoldButton->Down) // изменить данный стиль CurrText()->Style = CurrText()->Style “ fsBold;

else // сбросить данный стиль CurrText()->Style = CurrText()->Style ” fsBold;

} }

// Реакция на нажатие кнопки "Стиль шрифта курсив" void _fastcall TMainForm::ItalicButtonClick(TObject*) { if (iFUpdating)

{ if (ItalicButton->Down) // изменить данный стиль CurrText()->Style = CurrText()->Style “ fsltalic;

else // сбросить данный стиль CurrText()->Style = CurrText()->Style ” fsltalic;

} }

// Реакция на нажатие кнопки "Стиль шрифта подчеркнутый" void _fastcall TMainForm::UnderlineButtonClick(TObject*) { if (iFUpdating)

{ if (UnderlineButton->Down) // изменить данный стиль

CurrText()->Style = CurrText()->Style “ fsUnderline;

else // сбросить данный стиль CurrText()->Style = CurrText()->Style ” fsUnderline;

) }

// Изменение размера шрифта в допустимом интервале значений void _fastcall TMainForm::FontSizeChange(TObject*) {

int fontsize = atoi(FontSize->Text.c_str());

if ((iFUpdating) && (fontsize)) { if (fontsize < 1)

{ ShowMessage("Number must be between 1 and 1638.");

FontSize->Text =1; } else if (fontsize > 1638)

{ ShowMessage("Number must be between 1 and 1638");

FontSize->Text = 1638; } CurrText()->Size = atoi(FontSize->Text.c_str()) ;

} }

// Реакция на нажатие одной из кнопок выравнивания текста void _fastcall TMainForm::AlignClick(TObject* Sender) { if (IFUpdating)

{ TControl *oAliBtn = (TControl*)(Sender);

RichEditl->Paragraph->Alignment = (TAlignment)oAliBtn->Tag;

} }

// Реакция на выбор нового названия шрифта из списка void _fastcall TMainForm::FontNameChange(TObject*) { if (iFUpdating)

{ CurrText()->Name =

FontName->Items->Strings[FontName->ItemIndex] ;

} }

// Реакция на нажатие кнопки "Нумерованный список" void _fastcall TMainForm::BulletsButtonClick(TObject*) { if (iFUpdating)

RichEditl->Paragraph->Numbering =

(TNumberingStyle)BulletsButton->Down;

}

// Типовая проверка возможности выхода из приложения void _fastcall TMainForm::FormCloseQuery(TObject*, bool & CanClose)

{ try

{ CheckFileSaveO; } // сохранить изменения? catch (...)

{ CanClose = false; } // ошибка (поймано исключение) }

// Определение позиции регулятора линейки, выбранного мышью void_fastcall TMainForm::RulerItemMouseDown(TObject* Sender,

TMouseButton Button, TShiftState Shift, int X, int Y) { TLabel * oTmpLabel = (TLabel *)Sender;

FDragOfs = oTmpLabel->Width / 2;

oTmpLabel->Left = oTmpLabel->Left+X-FDragOfs;

FDragging = true;

}

// Перемещение мышью выбранного регулятора линейки void _fastcall TMainForm:':RulerItemMouseMove(TObject* Sender,

TShiftState Shift, int X, int /*Y*/) ( if (FDragging)

{ TLabel * oTmpLabel = (TLabel *)Sender;

oTmpLabel->Left = oTmpLabel->Left+X-FDragOfs;

) }

// Определение позиции регулятора ширины красной строки void_fastcall TMainForm::FirstIndMouseUp(TObject* Sender,

TMouseButton Button, TShiftState Shift, int X, int Y) { FDragging = false;

RichEditl->Paragraph->FirstIndent =

int((FirstInd->Left+FDragOfs-GutterWid) / RulerAdj);

LeftIndMouseUp(Sender, Button, Shift, X, Y) ;

}

// Определение позиции регулятора левого отступа параграфа void _fastcall TMainForm::LeftIndMouseUp(TObject* Sender,

TMouseButton, TShiftState, int, int) { FDragging = false;

RichEditl->Paragraph->LeftIndent =

int((LeftInd->Left+FDragOfs-GutterWid) / RulerAdj)-RichEditl->Paragraph->FirstIndent;

SelectionChange(Sender); // атрибуты форматирования

}

// Определение позиции регулятора правого отступа параграфа

void_fastcall TMainForm::RightIndMouseUp(TObject* Sender,

TMouseButton, TShiftState, int, int) { FDragging = false;

RichEditl->Paragraph->RightIndent =

int((Ruler->ClientWidth-Rightlnd->Left+FDragOfs-2) / RulerAdj)-2*GutterWid;

SelectionChange(Sender); // атрибуты форматирования }

// Активизация Файла помощи на Форме void _fastcall TMainForm::FormActivate(TObject* /*Sender*/) { Application->HelpFile = "RICHEDIT.HLP";

RichEditl->SetFocus() ;

Листинг 4.1. Кодовый файл Romain.cpp модуля редактора.

Рис. 4.22 демонстрирует работу со встроенным отладчиком на примере приложения редактора. Предположим, вы хотите узнать, правильно ли занеслось имя открытого файла в переменную FFileName. В процессе отладки вы будете пользоваться опциями контекстного меню Редактора кода, активизируемого нажатием правой кнопки мыши:

=> Найдите инструкцию, за работой которой вы хотите проследить, и нажмите клавишу F5 (или щелкните мышью слева от выбранной инструкции). Красный цвет отмечает строку останова программы. Повторное нажатие клавиши или повторный щелчок мышью снимет точку останова. => Командами меню Run [ Run (клавиша F9), Run | Run to Cursor (клавиша

F4) или одноименной опцией запустите приложение.

=> Если программа дошла до точки останова (а это должно случиться при работе отлаженных приложений), строка окрасится синим цветом, а перед ней появится символ " ^ ".

; => Командой Run | Step Over (клавиша F8) выполните выбранную инструк-; цию в пошаговом режиме.

=> Двойным щелчком мышью выберите переменную FFileName в тексте ин-|§ струкции и опцией Inspect (клавиши Alt+F5) проинспектируйте начальное ti4' значение - "Untitled".

Рис. 4.22. Некоторые приемы отладки.

=> Продолжите отладку (клавиша F9) и откройте любой файл в диалоге команды File | Open меню редактора.

=> Снова выполните выбранную инструкцию в пошаговом режиме. => Проинспектируйте новое значение выбранной переменной - она должна

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

Run | Program Reset.

4.6.8 Системные компоненты

Компоненты вкладки System палитры компонент

осуществляют включение в вашу программу 12 специализированных системных элементов управления.

4.6.8.1 TTimer

Эта компонента инкапсулирует таймерные функции Windows API: SetTimer и KillTimer и сама обрабатывает сообщения WM_TIMER.

Свойство Interval задает частоту возникновения события OnTimer. По умолчанию Interval=1000 (одна секунда). Временной интервал передается функции SetTimer в качестве параметра.

Для каждого таймера вашей программы заведите отдельную компоненту.

4.6.8.2 TPaintBox

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

Если компонента TPaintBox перенесена на форму, ваша программа может рисовать на поверхности поля рисования (канве) с помощью обработчика события OnPciinl. Цвет и шрифт, используемые при инициализации объектов канвы (TCanvas), определяются свойствами Color и Font. Если вы хотите рисовать на всей форме, воспользуйтесь обработчиком события OnPaint самой формы.

Чтобы сохранить относительное положение поля рисования неизменным, даже если пользователь изменит размеры формы, установите значение true свойства Align.

4.6.8.3 TFileListBox

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

Свойство Mask задает типы, а свойство FileType - атрибуты файлов, которые появятся в списке файлов. Имя и расширение выбранного файла можно будет вводить в область редактируемого ввода, если свойство FileEdit указывает на соответствующий объект класса TEdit. Чтобы снабдить имена файлов пиктограммами. установите значение true свойства ShowGlyphs.

TFileListBox является производной от класса TCustomListBox, причем ее функционирование определяется, в основном, компонентой TListBox.

4.6.8.4 TDirectoryListBox

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

TDirectoryListBox является производной от класса TCustomListBox, причем ее функционирование определяется, в основном, компонентой TListBox.

4.6.8.5 TDriveComboBox

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

Синхронизировать работу трех компонент TDriveComboBox, TDirectoryListBox и TFileListBox можно обработчиками событий OnChange первой и второй компоненты:

TForml->DriveComboBoxl->Change(Sender: TObject);

TForml->DirectoryListBoxl->Change(Sender: TObject);

Теперь, когда пользователь меняет дисковод в списке дисков, содержимое списков каталогов и файлов также обновится. Другой способ решения проблемы синхронизации связан с установкой значения DirectoryListBoxl свойства DirList в списке дисков, а также значения TFileListBox 1 свойства FileList в списке файлов".

4.6.8.6 TFilterComboBox

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

Свойство Filter задает фильтры, которые появятся в списке фильтров, а свойство Mask - конкретный фильтр, выбранный пользователем в поле редактируемого ввода.

Обычно, список фильтров сопровождается списком файлов. Синхронизировать работу этих компонент можно обработчиком события OnChange первой компоненты:

TForml->FilterComboBoxl->Change(Sender: TObject) ;

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

4.6.8.7 TMediaPlayer

Элемент управления устройствами мультимедиа, которые поддерживаются MCI-драйверами (Media Control Interface) операционной системы Windows. Данная компонента отображает стандартную панель (Рис. 4.23) с кнопками (Play, Stop, Eject и др.), позволяющими управлять такими устройствами как звуковая плата, компакт диск, видеокамера, AVI плеер, MIDI секвенсор.

Рис. 4.23. Петель управления устройствами мультимедиа.

Конкретное устройство задается свойством DeviceType (например, dtWaveAudio или dtVideodisc). Значение dtAutoSelect свойства DeviceType вызовет попытку автоматически выбрать тип устройства, а значение true свойства AutoOpen - открыть его вызовом метода Open. Если устройство сохраняет свои данные в файле, задайте имя этого файла в свойстве FileName.

4.6.8.8 TOleContainer

Организует связь с OLE объектами (Object Linking and Embedding) или непосредственно включает их в вашу программу.

Механизм OLE, являющийся расширением операционных систем Windows, реализует передачу данных от программы-сервера к другой программе-контейнеру. Например, ячейки электронной таблицы можно переносить в документ текстового процессора. Передача данных осуществляется через динамически отводимую память. В отличие от механизма обмена данными через доску объявлений (Clipboard), контейнеру OLE не требуются знания формата принимаемых данных. Любой сервер может выдавать свои данные любому контейнеру, который принимает их, без какой бы то ни было интерпретации формата.

Чтобы дать возможность пользователю создать OLE объект в режиме диалога, достаточно обратиться к методу InsertObjectDialog. Методы CreateObject и CreateObjectFromFile отвечают за создание включенного объекта, а метод CreateLinkToFile - за создание связанного с файлом объекта.

TOleContainer автоматически обслуживает процесс слияния меню, т.е. объединения контейнера элемента меню вашей формы с объектом замещения, который активизируется OLE сервером.

4.6.8.9 TDdeClientConv

Устанавливает режим динамического обмена данными (Dynamic Data Exchange) для программы DDE клиента. Используйте эту компоненту совместно с TDdeClientIlem, чтобы сделать ваше приложение DDE клиентом.

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

Для соединения с сервером и превращения вашего приложения в DDE клиента на этапе проектирования, установите имя программы сервера в свойстве DdeService, а тему разговора (имя формы или имя текстового файла) - в свойстве DdeTopic. В окне диалога установок режима DDE Info нажмите кнопку Paste Link.

Во время работы программы эти действия реализует метод Setlink. Чтобы послать текстовую строку связанному элементу сервера, воспользуйтесь методом PokeData, а для посылки макрокоманды на исполнения сервером обратитесь к методу ExecuteMacro.

Если значением свойства ConnectMode задан автоматический режим разговора ddeAutomatic, клиент попытается установить связь при создании компоненты в момент исполнения программы. Если значением свойства ConnectMode задан режим разговора ddeManual, то для установки связи вы должны написать обработчик события ОпОреп, который вызывает метод OpenLink.

4.6.8.10 TDdeClientltem

Определяет элемент динамического обмена данными DDE клиента. Укажите имя объекта компоненты TDdeClientConv в свойстве DdeConv, a элемент обмена - в свойстве Ddeltem. Если компонента TDdeClientConv установила связь с DDE сервером, он будет автоматически и последовательно обновлять данные клиента, пока разговор не завершится.

Каждый раз, когда сервер производит обновление данных клиента, новая текстовая строка автоматически заносится в свойство Text, и возникает событие OnChange. При обмене строками длиннее 255 символов они будут передаваться через список свойства Lines, причем первая строка Lines переносится в Text.

4.6.8.11 TDdeServerConv

Устанавливает режим динамического обмена данными для программы DDE сервера. Используйте эту компоненту совместно с TDdeServerItem, чтобы сделать ваше приложение DDE сервером. Тема разговора является значением свойства Name.

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

Использование компоненты TDdeServerConv не обязательно: если вы не поместили ее на форме, клиент будет по-прежнему посылать запросы на обновление своих данных непосредственно из компоненты TDdeServerItem. В этом случае темой разговора является имя формы, на которой находится компонента TDd eServerItem.

4.6.8.12 TDdeServerltem

Определяет элемент динамического обмена данными DDE сервера. При использовании этой компоненты вместе с TDdeServerConv имя сервера указывается значением свойства ServerConv.

Каждый раз. когда клиент посылает запрос на обновление своих данных. сервер посылает ему содержимое свойства Text, и возникает событие OnCliange. При обмене строками длиннее 255 символов они будут передаваться через список свойства Lines, причем первая строка Lines переносится в Text.

Чтобы протестировать связь с DDE клиентом, воспользуйтесь методом CopyToClipboard, который будет копировать содержимое свойства Text (или Lines) и информацию о связи на доску объявлений. При активизации клиента вы сможете забрать DDE данные с доски объявлений в программу клиента.

4.6.9 Компоненты отчетов

Вкладка QReport палитры компонент

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

Эти компоненты позволяют визуально конструировать стилизованные отчеты по данным, поставляемым любым источником, включая таблицы и запросы компонент доступа к базам данных TTable и TQuery. Отчеты могут содержать поля заголовков, колонтитулов, сносок и итогов. QReport предоставляет мощные средства отображения отчетов в разных видах, автоматического подведения итогов и подсчета полей - на любом уровне группировки данных отчета.

4.6.9.1 TQuickReport

Представляет и распечатывает данные в виде стилизованных отчетов QuickReport. Это основная компонента используется совместно с TDataSource и одной или несколькими TQRBand. Дважды щелкнув мышью по компоненте или выбрав опцию Preview Report из контекстного меню, вы откроете окно просмотра отчета. Укажите источник данных в свойстве DataSource. Чтобы заполнить окно просмотра отчета или напечатать его, обратитесь к методам Preview или Print.

4.6.9.2 TQRBand

Каждый образец этой компоненты отвечает за представление и печать своего поля (полосы) отчета. Свойство BandType содержит выпадающий список вариантов полос отчета (заголовки, колонтитулы, сноски, вложенные поля деталировок, итоги и т.д.), из которого вы выбираете ту полосу, которую будет обсуживать данная компонента. Распечатка одних полос отчета будет происходить автоматически, а распечатка других потребует связи с компонентами TQRGroup или TQRDetailLink.

4.6.9.3 TQRGroup

Поддерживает работу с групповой полосой отчета.

4.6.9.4 TQRDetailLink

Поддерживает работу с перекрестными ссылками на вложенные полосы деталировки, осуществляя связь по принципу master-detail.

4.6.9.5 TQRLabel

Отображает текст в виде заголовков столбцов отчета. Вы можете менять статический текст заголовка в свойстве Caption в любой момент во время подготовки отчета. Если вам требуется выводить текст поля записи некоторого набора базы данных, следует воспользоваться компонентой QRDBText.

4.6.9.6 TQRMeino

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

4.6.9.7 MTQRDBText

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

4.6.9.8 TQRDBCalc

Автоматизирует процесс суммирования и подсчета полей в наборе данных источника.

4.6.9.9 TQRSysData

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

4.6.9.10TQRShape

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

4.6.9.11 TQRPreview

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

4.6.9.12 Пример использования компонент отчетов

C++Builder поставляется вместе с примером, который демонстрирует следующие разновидности работы с компонентами отчетов:

• создание этикеток для почтовых отправлений;

• создание простого отчета;

• модификация оригинальных предварительных видов печати;

• разработка отчетов по принципу master-detail;

• сохранение выборочных текстовых файлов детализации.

Рис. 4.24. Форма приложения для работы с отчетами.

Удостоверьтесь предварительно, что локальный псевдоним (alias) демонстрационной базы данных BCDEMOS установлен с помощью утилиты конфигурации

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

=? По команде главного меню File | Open Project откройте диалог выбора проектов.

=> Войдите в каталог \.. .\CBuilder\Examples\Dbtasks\Quickrpt.

=> Выберите проектный файл с именем Qrdemo и нажмите кнопку Open. Рис. 4.24 показывает форму демонстрационного приложения Quick Report.

=> Командой главного меню Run | Run запустите процесс компиляции и сборки приложения.

=> После вызова программы поэкспериментируйте с разными опциями.

4.6.10 Компонента ActiveX

Входящие в варианты поставки C++Builder Professional и C++Builder Client/Server Suite компоненты обеспечивают поддержку промышленного стандарта ActiveX/OCX. Созданные вами или третьими лицами компоненты Delphi ActiveX можно интегрировать в среду так, чтобы они вошли в Палитру компонент для немедленного использования. В частности, вы можете расширить стандартный вариант Палитры новыми компонентами ActiveX, включив пакет NetManage для обучения и разработки приложений в сети Internet. В конце главы 6 вы найдете подробную инструкцию того, как это делается. В типовом варианте поставки C++Builder Standard вкладка ActiveX палитры компонент

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

4.6.10.1 ChartFX

Дважды щелкнув мышью по компоненте или выбрав опцию Properties из ее контекстного меню. вы откроете диалоговое окно установок вида и множества других характеристик диаграммы. Свойства, методы и события компоненты ChartFX обеспечивают выполнение следующих основных операций над диаграммами:

• Создание простых диаграмм.

• Передача исходных данных в новую диаграмму.

• Редактирование данных в существующей диаграмме.

• Изменение легенд, заголовков и других визуальных атрибутов диаграммы (видов, цветов, орнаментов заливки, шрифтов, координатных сеток и т.д.).

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

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

4.7 Дизайнер меню

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

Чтобы начать процесс создания меню: __

1. Поместите значок компоненты MainMenu или PopUpMenu из вкладки стандартных компонент на вашу форму.

2. Откройте окно дизайнера меню. Оставив значок компоненты выбранным, дважды щелкните на нем левой кнопкой мыши или выберите опцию Menu Designer из контекстного меню компоненты. (Открыть контекстное меню дизайнера можно щелчком правой кнопкой мыши в любом месте его окна или нажатием клавиш Alt+FlO).

3. Введите имя меню и нажмите клавишу Enter, если желаете изменить имя, установленное по умолчанию (MainMenul).

Чтобы добавить команды в меню:

1. Выберите позицию, в которую вы хотите поместить новую команду.

2. Введите название команды (или символ "-", если вы хотите добавить разделительную черту в выпадающий список команд) и нажмите клавишу Enter. Указанному названию (Caption) C++Builder автоматически поставит в соответствие некоторый идентификатор (Name) и занесет в Инспектор объектов. Так команде меню File ставится в соответствие идентификатор Filel, а русскоязычному названию Файл - порядковый номер идентификатора с префиксом N. Если названию предшествует символ "&", то обращение к соответствующей команде меню можно выполнять совместным нажатием клавиш Alt+первая (подчеркнутая) буква названия. Можно задать любую комбинацию "горячих" клавиш или выбрать ее из списка ShortCut Инспектора объектов.

3. Нажмите клавишу Enter, чтобы перейти к добавлению следующей команды выпадающего списка или клавишу Esc, чтобы вернуться в главное меню. С помощью левой кнопки мыши или клавиш позиционирования <-, ->, Г, ^ можно перемещаться по списку и переходить в главное меню. Повторное нажатие клавиши Enter завершает процесс.

Чтобы вставить поле для новой команды в меню:

1. Выберите элемент меню, рядом с которым вы собираетесь сделать вставку.

2. Нажмите клавишу Ins или выберите опцию Insert из контекстного меню. Поле новой команды вставляется над выбранным элементом в выпадающем списке или слева от выбранного элемента в главном меню.

Чтобы удалить команду из меню:

1. Выберите команду, которую вы собираетесь удалить.

2. Нажмите клавишу Del или выберите опцию Delete из контекстного меню.

Чтобы создать поле для вложенного подменю:

1. Выберите элемент, для которого вы хотите создать подменю.

2. Нажмите клавиши Ctrl+-> или выберите опцию SubMenu из контекстного меню.

Чтобы переместить элемент:

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

2. Отпустите кнопку мыши.

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

Чтобы добавить шаблон к вашему меню:

1. Выберите опцию Insert From Template из контекстного меню.

2. Выберите нужный шаблон из предложенного списка и нажмите кнопку ОК или клавишу Enter. Элементы шаблона образуют подменю элемента, на который указывал курсор в выпадающем списке команд, или создадут новый элемент в главном меню.

Чтобы сохранить ваше меню в виде шаблона:

1. Выберите опцию Save As Template из контекстного меню.

2. Введите имя шаблона и нажмите кнопку ОК или клавишу Enter.

Чтобы удалить шаблон:

1. Выберите опцию Delete Templates из контекстного меню.

2. Выберите нужный шаблон из списка и нажмите кнопку ОК или клавишу Enter. Внимание: Данный шаблон будет удален не только из списка, но и из файла шаблонов BCB.DMT на жестком диске.

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

Чтобы организовать слияние меню во время выполнения:

1. Выберите меню, которое вы хотите активизировать из выпадающего списка свойства Menu вашей формы. Операции слияния применимы только к активному меню. Если форма содержит несколько компонент меню, вы можете переключать активное меню во время выполнения программы, устанавливая новые значения свойства Menu, например: Forml->Menu = ВтороеМеню;

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

на разделяемой панели главного меню: чем меньше номер свойства Grouplndex, тем

левее располагается соответствующая команда. Пусть главное (активное) меню содержит только две команды: "Файл" (Grouplndex=0) и "Справка" (5). Тогда между ними разрешается вставить до четырех команд из меню другой формы-потомка с номерами 1,2,3, и 4, например, "Редактор" (1) и "Формат" (3). Далее можно заместить команду "Формат" (3) на команду "Работа" (3) из меню другой формы-потомка.

Рис. 4.25 иллюстрирует процесс проектирования меню на форме прототипа тестового приложения, предназначенного для обработки файлов. Открыв контекстное меню дизайнера, обратите внимание на опцию Insert From Resource. Судя по названию, она должна давать возможность создавать меню на базе ресурсных файлов с расширением .гс. К сожалению, автору не удалось заставить дизайнер использовать ресурсы приложений, ранее написанных на Borland C++ версии 4.5. Будем надеяться, что в широко рекламируемой версии 5.02 эта недоработка будет исправлена.

Имя меню
Главное меню
Выпадающий список команд
Контекстное меню дизайнера

Рис. 4.25. Проектирование меню с помощью дизсшчера.

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

4.8 Итоги

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