Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Теллес М. - Borland C++ Builder. Библиотека программиста - 1998

.pdf
Скачиваний:
790
Добавлен:
13.08.2013
Размер:
4.35 Mб
Скачать

Borland C++ Builder (+CD). Библиотека программиста 301

{

FAngle = Angle; Repaint();

}

}

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

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

Рис. 14.4. Корректно работающий компонент AngleText

Инсталляция и повторное тестирование компонента

Инсталляция нашего компонента ничем не отличается от инсталляции любого другого компонента. Выберите команду меню Component|Install и нажмите на кнопку Add (добавление). В появившемся небольшом окне диалога нажмите кнопку Browse (обзор) и перейдите к исходному файлу компонента, который находится в директории вашего текущего проекта. Выберите его и нажмите кнопку OK, чтобы закрыть окно. Далее все время нажимайте кнопку OK, пока не закроете окно инсталляции компонента. При этом CBuilder скомпилирует и соберет библиотеку VCL для использования в системе. По окончании (естественно, только в том случае, если при компиляции не возникнет ошибок), палитра компонентов (Component Palette) будет перестроена так, что ваш компонент отобразится в той страницы палитры, которую вы указали в функции Register. Если вы взгляните на код исходного файла, то увидите, что CBuilder автоматически сгенерировал функцию Register для вашего компонента:

namespace Angletext

{

void __fastcall Register()

{

TComponentClass classes[1] = {__classid(TAngleText)}; RegisterComponents("Samples", classes, 0);

Borland C++ Builder (+CD). Библиотека программиста 302

}

}

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

Иконка

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

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

Resource Workshop, который поставляется с Borland C++, или Resource Editor, поставляемый с

Visual C++. Создайте новый файл ресурса, содержащий иконку, и назовите его <компонент.rc> (где компонент имя, совпадающее с именем файла, содержащего компонент). Встройте скомпилированный файл ресурсов в откомпилированную форму и переименуйте его в файл DCR. CBuilder автоматически поместит эту иконку в нужную страницу палитры компонентов. Наиболее тонким моментом здесь является то, что идентификатор ресурса для растрового изображения в файле ресурсов должен совпадать с именем компонента. Если, к примеру, у вас есть компонент с именем TNewControl, то идентификатор ресурса должен быть TNEWCONTROL (идентификаторы растровых изображений не различают прописные и заглавные буквы, но является общепринятым писать их в заглавных буквах).

Подготовка компонента к распространению

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

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

Когда вы инсталлируете компонент, вам надо скопировать OBJ-файл и заголовочный файл (.h) в директорию lib вашего дерева каталогов CBuilder. После того, как вы это сделаете, компилятор и компоновщик (линкер) смогут найти файлы, необходимые им для работы системы.

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

На этом наш первый пример проектирования и разработки компонентов завершен. На нем мы научились создавать новый компонент, добавлять в него свойства и опубликовывать их для того, чтобы они были отражены в Object Inspector системы CBuilder. Теперь мы рассмотрим некоторые

новые аспекты проектирования и разработки компонентов на примере создания более сложного компонента — FilterEdit.

Borland C++ Builder (+CD). Библиотека программиста 303

Компонент FilterEdit

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

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

Формулировка проблемы

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

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

Частное решение

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

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

Общее же решение это отдельный вопрос. Давайте займемся им.

Общее решение

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

Borland C++ Builder (+CD). Библиотека программиста 304

информации, и эти блоки станут свойствами нашего управляющего компонента. Первым свойством станет информация о том, какие данные являются разрешенными (или запрещенными) для ввода в управляющий элемент. Для наших целей вполне подойдет строка, в которой будут перечислены все символы, отвечающие этому условию. Это заодно позволит вам набраться опыта в работе со свойствами, тип которых не является базовым. Вторым свойством станет флаг, показывающий, являются ли символы в строке теми, кроме которых вводить ничего нельзя (значение флага = true), или же теми, которые вводить нельзя (значение флага = false). Свойство, определяющее набор символов, мы назовем Allowed (для разрешенных символов), а свойство-флаг

— Include (то есть будут ли символы включены в текст, или нет).

Воплощение базового компонента

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

#include <vcl\System.hpp> //-------------------------------------------------------------------

class TFilterEdit : public TCustomEdit

{

private:

System::AnsiString FFilterString; bool FbInc;

protected:

virtual void __fastcall KeyPress(char &Key); public:

__fastcall TFilterEdit(TComponent* Owner); __published:

__property System::AnsiString Allowed = {read=FFilterString, write=FFilterString};

__property bool Include = {read=FbInc, write=FbInc, default=true}; };

В данном случае мы добавляем несколько внутренних переменных-членов класса для хранения фактических значений свойств и замещаем функцию KeyPress — член класса TCustomEdit для собственно фильтрования вводимых данных.

Мы добавили свойство Allowed, которое представляет из себя строку типа AnsiString, и свойство Include, выступающее в качестве флага, логического (boolean) типа. Обратите внимание на то, что тип AnsiString заключен в области (namespace) System, так что нам надо задавать его, используя оператор разрешения видимости System:: для того, чтобы сообщить компилятору, где находится тип AnsiString. Кроме того, мы должны подключить заголовочный файл System.hpp из каталога заголовочных файлов системы (CBuilder\include\vcl) чтобы получить описание класса. Object Inspector и другие инструменты CBuilder понимают тип AnsiString, так что пользователь сможет редактировать эти строки, используя стандартный редактор строк системы.

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

Borland C++ Builder (+CD). Библиотека программиста 305

сделанным нами ранее:

__fastcall TFilterEdit::TFilterEdit(TComponent* Owner) : TCustomEdit(Owner)

{

FbInc = true;

}

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

void __fastcall TFilterEdit::KeyPress(char &Key)

{

// Проверяем нажатие клавиши

for ( int i=0; i<FFilterString.Length(); ++i ) if ( Key == FFilterString[i] )

if ( FbInc ) return; else

{

Key = 0; return;

}

//Не нашли вводимого символа

//Очень плохо

if ( FbInc ) Key = 0;

}

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

Сужение проблемы класс TNumericEdit

После того, как компонент TFilterEdit создан, можно создать базирующийся на нем класс TNumericEdit. Этот класс даже проще, чем TFilterEdit, поскольку он допускает ввод только числовых значений. Для того, чтобы двигаться дальше, придется сначала откомпилировать и сынсталлировать компонент TFilterEdit, проделав всю обычную процедуру. Для того, чтобы убедиться в том, что компонент работает должным образом, протестируйте его, вводя различные значения для Allowed и Include. Если все хорошо, можно делать следующие шаги.

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

Borland C++ Builder (+CD). Библиотека программиста 306

возможностей. Помните после того, как вы сынсталлировали компонент, он становится частью базовой системы CBuilder. Нет никаких различий между компонентом, который написали вы и компонентом, созданным командой Borland VCL. Возможность расширять систему CBuilder делает ее идеальной для работы в корпоративной среде.

Сынсталлировав компонент TFilterEdit, воспользуйтесь Мастером компонентов для создания нового компонента TNumericEdit. У этого нового компонента предком будет класс TFilterEdit (который теперь тоже будет присутствовать в комбинированном списке).

Все, что вам надо изменить в кода для класса TNumericEdit, это конструктор класса для того, чтобы инициализировать свойства Include и Allowed так, чтобы пользователь мог вводить только числовые значения. Вот как будут выглядеть эти изменения:

__fastcall TNumericEdit::TNumericEdit(TComponent* Owner) : TFilterEDit(Owner);

{

Allowed = "1234567890"; Include = true;

}

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

void __fastcall TForm1::FormCreate(TObject *Sender)

{

pEdit = new TNumberEdit(this); pEdit->Left = 10;

pEdit->Top = 10; pEdit->Width = 100; pEdit->Height = 30; pEdit->Parent = this;

pEdit->Allowed = "ABCDEFG"; pEdit->Include = false;

}

Если вы теперь добавите заголовочный файл для компонента TNumericEdit в эту форму, то увидите, что приведенный выше код скомпилируется без ошибок. В чем же здесь дело? Проблема состоит в том, что свойства из компонента TFilterEdit были унаследованы в TNumericEdit, и пользователь имеет возможность заместить те установки, которые вы сделали в классе вашего нового компонента. Это нормальное поведение класса C++, так как раздел __published описания класса аналогичен секции public. Очевидно, что подобный вариант работы нашего компонента нас не устраивает. Есть ли возможность как-то справиться с возникшей проблемой не переписывая весь код для базового компонента заново? В некотором роде да. Итак, на самом деле проблема со свойствами, описанными в разделе __published, состоит в том, что эти свойства всегда будут доступы в любом наследующем классе. То есть, другими словами, мы не можем перекрыть программисту возможность использования свойств Allowed и Include в классах-наследниках при теперешнем положении вещей.

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

Borland C++ Builder (+CD). Библиотека программиста 307

class TBaseFilterEdit : public TCustomEdit

{

private:

System::AnsiString FFilterString; bool FbInc;

protected:

virtual void __fastcall KeyPress(char &Key);

__property System::AnsiString Allowed = {read FFilterString; write FFilterString};

__property bool Include = {read=FbInc; write=FbInc; default = true}

public:

__fastcall TBaseFilterEdit(TComponent* Owner) : TCustomEdit(Owner)

{

}

__published: };

Теперь класс TFilterEdit будет выглядеть так: class TFilterEdit : public TBaseFilterEdit

{

private:

protected:

public:

__fastcall TFilterEdit(TComponent* Owner); __published:

__property Allowed; __property Include; };

В этом классе свойства Allowed и Include заново помещаются в секцию __published, чтобы конечный пользователь мог видеть их в Object Inspector. Класс TNumericEdit также наследует от класса TBaseFilterEdit:

class TNumericEdit : public TBaseFilterEdit

{

private:

protected:

public:

__fastcall TNumericEdit(TComponent* Owner); __published:

};

Обратите внимание на то, что в этом классе свойства Allowed и Include не переопределяются, так что компонент типа TNumericEdit не позволяет конечному пользователю использовать эти свойства. Внутри класса существует прямой доступ к свойствам Allowed и Include, поскольку они являются защищенными членами класса. Переменные-члены класса, представляющие эти свойства в базовом классе (FbInc и FFilterString) недоступны в обоих наследующих классах. Полный исходный код всех трех классов может быть найден как вы уже догадались на прилагаемом компакт-диске.

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

Borland C++ Builder (+CD). Библиотека программиста 308

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

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

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

Компонент LineGraph

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

Давайте займемся разработкой такого графического компонента.

Формулировка проблемы

Цель нашего компонента позволить пользователю рисовать сравниваемые графики для наборов данных, с которыми он работает. Этот компонент должен предоставлять возможности: масштабировать данные в соответствии с границами, задаваемыми пользователем; рисовать разные линии разными цветами; выводить на экран некоторое количество пометок. Главная цель компонента позволить пользователю сравнивать данные, так что он должен поддерживать отображение нескольких графиков одновременно, кроме того, он должен сохранять информацию при всех перемещениях и изменениях размера.

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

Частное решение

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

Borland C++ Builder (+CD). Библиотека программиста 309

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

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

После того, как проблема, которую разрешает компонент, определена, наступает следующий этап

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

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

Компонент, который мы собираемся создать, будет называться LibeGraph. При помощи Мастера компонентов CBuilder создайте новый компонент с таким именем, наследующий от класса TCustomControl. Мы используем этот класс, поскольку нам не понадобится от него ничего, кроме основных возможностей работы с окнами, но нам надо, чтобы у нашего компонента было свой поле (Canvas), на котором мы будет рисовать графики. Класс TCustomControl — это основной компонент, предоставляющий возможности работы с окнами в системе VCL.

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

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

public:

__property Graphics::TColor LineColors[int nIndex] = {read=GetLineColor, write=SetLineColor}; __property double XPoint[int nLine][int Index] = {read=GetXPoint, write=SetXPoint};

__property double YPoint[int nLine][int Index] = {read=GetYPoint, write=SetYPoint};

__published

__property int NumberXTicks =

{read=FNumXTicks, write=FNumXTicks, default=5}; __property int NumberYTicks =

{read=FNumYTicks, write=FNumYTicks, default=5}; __property double XStart = {read=FXStart, write=FXStart}; __property double YStart = {read=FYStart, write=FYStart}; __property double XIncrement = {read=FXInc, write=FXInc}; __property double YIncrement = {read=FYInc, write=FYInc}; __property int NumberOfPoints =

{read=FNumPoints, write=SetNumberOfPoints, default=0}; __property bool XGrid = {read=FXGrid, write=FXGrid,

default=true};

__property bool YGrid = {read=FYGrid, write=FYGrid,

Borland C++ Builder (+CD). Библиотека программиста 310

default=true}; __property int NumXDecimals =

{read=FXNumDecimals, write=FXNumDecimals, default=2}; __property int NumYDecimals =

{read=FYNumDecimals, write=FYNumDecimals, default=2}; __property int NumberOfLines =

{read=FNumberOfLines, write=SetNumberOfLines, default=2};

Как вы, наверное, отметили, список получился довольно длинный. У компонента LineGraph довольно много возможностей, поэтому и свойств у него достаточно много. Еще вы конечно обратили внимание на то, что не все свойства компонента сделаны __published. Некоторые свойства перечислены в секции public. Зачем нам это понадобилось?

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

Давайте для начала рассмотрим как раз свойства-массивы. У нас есть три таких свойства для X- координат точек графиков, Y-координат точек графиков и цветов различных линий графиков. Координаты точек по X и по Y это двумерные массивы, поскольку мы рассматриваем линии как массивы точек. Так что эти два свойства это массивы линий, которые являются массивами точек. Цвета представлены одномерным массивом, поскольку каждой линии графика соответствует единственный цвет.

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

pLineGraph->XPoints[0][0] = 10.0;

pLineGraph->YPoints[0][0] = 10.0;

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

pLineGraph->LineColors[0] = clRed;

Замечание

В CBuilder индексы в массивах не обязательно должны быть целыми значениями, как это было в C и C++. Вы можете также использовать строки, объекты, или что-нибудь еще по своему желанию. Это является основой свойства FieldValue в классе компонента TDataSet.

Остальные свойства, как нетрудно догадаться, также относятся к графику. Свойства NumberXTicks и NumberXTicks относятся к количеству отметок (делений), используемых для осей графика. Значения XStart и XStart представляют собой начало осей X и Y, а значения XIncrement и XIncrement являют размер «шага» осей, то есть расстояния между делениями на осях.

Соседние файлы в предмете Программирование на C++