1 Что такое bde?
Вид материала | Документы |
- Т. П. Возможно ли «объективистское» религиоведение?, 75.66kb.
- Десять нерешенных проблем теории сознания и эмоций. Эмоции, 306.48kb.
- Тема: Что такое вич? Что такое вич- инфекция? Что такое спид?, 31.26kb.
- 1. что такое нефтехимия, 823.72kb.
- Сочинение. Что такое словесный мусор?, 32.51kb.
- Для начала разберемся в базовых определениях. Разберем, что такое вычислительная сеть, 81.21kb.
- Павел Рогозин, 2063.97kb.
- Задачи: образовательные: объяснить детям, что такое пожар; познакомить со средствами, 42.31kb.
- Что такое реинжиниринг, 33.49kb.
- Наркотики – страшное зло, 13.34kb.
1.1. Что такое BDE? 1
1.2. Базы данных в BDE 1
1.3. Создание alias. 2
1.4. Косметическая настройка BDE 3
1.5. Таблица в Database Desktop 4
1.6. Мастер форм 4
1.7. Каким образом это все работает. 5
1.8. Компонент TTable. Создание таблиц. Типы полей 6
1.9. Создание таблиц. Ключи и индексы 8
1.10. Класс TFieldDef. 9
1.11. Коллекция TFieldDefs 10
1.12. Изменение значений полей 12
1.13. Проект приложения CView 13
1.14. Создание произвольной таблицы 15
1.1.Что такое BDE?
BDE - в C++Builder механизм управления базами данных. Это посредник между Вашей программой и базами данных разных форматов - Paradox, MS Access, dBase и так далее. BDE - набор системных DLL файлов, которые включатют драйвера. Вашей программе не придется вручную эти самые драйвера создавать, просто можно воспользоваться встроенным механизмом.
В C++Builder BDE не является монополистом. В программу включены также такие механизмы, как ADO и InterBase.
ADO представляет собой также набор библиотек, как и BDE. В отличие от их обоих, InterBase позволяет обращаться к базам данных через COM-интерфейсы, минуя посреднические механизмы. В этом плане InterBase более эффективен для распространения, поскольку нет необходимости включать установочный файл BDE в дистрибутив программы, который, кстати, имеет большой размер.
В любом случае BDE манипулировать проще всего.
Основное для работы с базами данных церез BDE предоставляется на палитрах Data Access и Data Controls.
BDE имеет довольно мощные средства для работы с SQL. SQL - язык транзакций RDBMS реляционных баз данных.
^
1.2.Базы данных в BDE
Чаще всего базы данных адресуются в программах своим псевдонимом [alias]. Псевдоним - приблизительно то же самое для базы данных, что и домен для сайта. То есть через псевдоним можно обращаться к базе данных, не зная ее физического расположения.
Чтобы узнать, какие alias есть на Вашем компьютере, нужно запустить командой Database-Explore т.н. SQL Explorer. Его окно показано на скриншоте:
В левой части показаны псевдонимы баз данных, в правой - их свойства. Отметьте, что получить доступ к базе данных можно только с установленным сервером этой базы. Например, после установки InterBase сервера становится доступным база данных IBLocal. Сразу же доступными являются базы данных BCDEMOS и DBDEMOS.
Никто не ограничивает Вас в выборе alias. Можно создать и свой собственный alias для рабочих файлов.На скриншоте виден псевдоним Local tables, как раз в нем все примеры баз данных и размещены.
С BDE поставляется довольно много примеров баз данных. Эти таблицы, как и все другие, можно посмотреть, если два раза щелкнуть на BCDEMOS, а затем на появившемся Tables.
^
1.3.Создание alias.
Запустите SQL Explorer командой Database-Explore. Как обычно, alias с левой, свойства с правой строны. Выберите команду Object-New. Появится оконо:
Оконо дает возможность выбрать тип драйвера для базы данных. Стандартный нам подходит. Жмите OK.
Слева появится поле для ввода имени для таблицы. Введем, например, "Local tables", и нажмем Enter. Обратите внимание, что рядом со значком базы данных в данный момент изображена зеленая стрелка. Эта стрелка означает, что над базой проводятся изменения типа транзакции. Чтобы изменения вошли в силу, надо из контекстного меню выбрать команду Apply.
Для того, чтобы Explorer знал, откуда брать таблицы, нужно задать путь к директории с таблицами. Например каталог "C:\program files\borland\database desktop\workdir".
После всех этих махинаций можно выполгить команду Apply. До ее выполнения ничего работать не будет, а возникнет ошибка "Operation not supported":
Теперь все таблицы, помещенные в эту директорию, Проводник будет отображать в раскрывающемся дереве.
^
1.4.Косметическая настройка BDE
Чтобы работать с BDE, надо ее немного поднастроить, чтобы русский выводила как положено. Для настройки BDE используется утилита BDE Administrator. Выглядит она довольно схоже с SQL Explorer'ом:
Вкладка Databases нам не нужна, мы ее и из Проводника видим. Зато на вкладке Configuration есть настройки по драйверам баз данных и системным параметрам.
Открываем ветвь Drivers. Там должны быть пункты Native и ODBC. Второй нам пока не нужен, открываем первый. Там есть значок Paradox. По нему и щелкаем. В правой части, как обычно, свойства. Пока установим правлильный драйвер для языка, как на скриншоте:
Чтобы в Database Desktop отображался нормальный шрифт, нужно в файл win.ini, в раздел FontSubstitutes подставить строку Arial,0=Arial,204. После этого перезагрузиться.
^
1.5.Таблица в Database Desktop
Запускается Database desktop через Tools-Database Desktop.
Выбираем команду File-New-Table, появляется окно, в котором предлагается выбрать тип создаваемой таблицы. Выберем Paradox 7. Жмите OK. Появится другое окно:
Кто работал с MS Access в режиме конструктора. Первый столбец - номер поля, второй - его имя. Третий определяет тип (выпадающий по правой клавише мыщи список), четвертый - размер, а пятый - является ли поле ключевым. Для начала - строковые типы - ALPHA, числовые - NUMBER. Поля, то есть столбцы, когда они уже готовы, создаются как обычно. Для начала создайте простую записную книжки и нажмите Save as для сохранения таблицы. Внизу можно выбирать alias для сохранения.
^
1.6.Мастер форм
Попробуем создать форму на основе базы данных, используя Мастер форм (Form Wizard). Этот мастер запускается командой Database-Form Wizard... Как и у всякого другого мастера, у него несколько окон.
В первом окне предлагается выбрать, какие компоненты будет использовать форма. Для начала лучше согласиться с вариантами по умолчанию, поскольку мы используем простую таблицу, без связи ведущий-ведомый, а запросы нам пока не нужны.
В следующем окне предлагается выбрать источник для построения формы. Выберите alias базы данных в выпадающем списке справа внизу, и название таблицы слева. Предпочтительнее выбрать таблицу из BCDEMOS, называемую Clients.
Жмите Next. Далее будет предложено выбрать поля из таблицы, которые будут использоваться в форме. Можно выбрать все поля кнопкой ">>". Если какие-то Вам не подходят, уберите их.
В следующем окне мастера будет предложен вариант размещения полей таблицы.
В последнем окне этого, довольно долгого мастера, Вас спросят, нужно ли создавать модуль данных и является ли создаваемая форма главной.
В итоге получится:
^
1.7.Каким образом это все работает.
Общая схема работы типичного BDE-приложения базы данных такова:
[База данных]
|
BDE
|
Компоненты доступа к BDE [TTable, TQuery]
|
Компонент TDataSource
|
Компоненты Data Controls [TDBLabel, TDBEdit]
|
Пользователь
Это не единственный вариант доступа к базе данных. Как уже отмечалось, есть еще ADO и InterBase. Но общий принцип работы такой.
В данном случае всю информацию о доступе к конкретной базе данных в данной программе хранит TTable. В ней и были заданы свойства DatabaseName и TableName. В компоненте же DataSource1 был задан набор данных как Table1. После этого DataSource стал промежуточным звеном между таблицей и компонентами TDBEdit и TDBImage, отвечавшими за отображение и редактирование записей.
Последние компоненты "понимают", к какому полю таблицы относятся, по свойству FieldName.
^
1.8.Компонент TTable. Создание таблиц. Типы полей
Этот компонент отвечает за системное соединение с выбранной базой данной и соответствующей таблицей. Для подключения используется текущая конфигурация BDE. Выбранный alias задается в свойстве DatabaseName, а выбранная таблица в свойстве TableName.
При этом этот компонент автоматически сканирует все возможные таблицы для предоставления доступа к ним. Если для доступа к выбранной базе (например, MS Access 97 Database) необходим ввод логина и/или пароля, при соединении появится дилоговое окно. Это окно чаще всего используется при доступе к базам данных ODBC.
Свойство Active таблицы дает возможность активировать ее уже на стадии выполнения. При этом автоматически тестируется соединение. Если при подобном тестировании вылетает какая-нибудь ошибка, чаще всего это какая-то ошибка настройки alias.
Но этот компонент может не только считывать данные с уже готовых таблиц. С его помощью можно создать и таблицу с "нуля". Так, в принципе, и должно быть, ведь каждая серьезная программа баз данных должна это уметь.
Насчет создания таблиц. Как мы знаем, таблица определяется полями и их типами. Типы бывают разные. Можно привести их все, правда, много места займет. DD - это Database DeskTop.
Название поля в DD | Константа | Описание |
| ftUnknown | Неизвестный, неограниченный тип. |
Alpha A | ftString | Одиночный символ или целая строка. |
Short S | ftSmallInt | Короткое целое, размерностью 16 бит. |
Integer I | ftInteger | Стандартное целое, размерность 32 бит. |
| ftWord | Слово - целое размерностью 16. В отличие от short, не имеет знака. |
Logical L | ftBoolean | Логическая переменная - принимает значения true |
| ftFloat | Число с плавающей точкой. |
| ftCurrency | Всеми нами любимая валюта - спецформат :). |
| ftBCD | Поле, содержащее кодированное в бинарном формате десятичное значение. |
Date D | ftDate | Дата - тоже специальный формат. |
Time T | ftTime | Аналогично время. |
| ftDateTime | И дата, и время в одном флаконе :) |
Bytes Y | ftBytes | Фиксированное количество байтов. |
| ftVarBytes | Вариантное (нефиксированное) количество байтов. |
AutoIncrement + | ftAutoInc | Поле-автоинкремент, которое увеличивается автоматически при добавлении новой записи. |
| ftBlob | Большой Бинарный ОБъект - оюычно что-то вроде изображения. |
Memo M | ftMemo | Поле типа Memo. В обще по своей структуре напоминает AnsiString - неограниченный размер. |
Graphic G | ftGraphic | Поле типа Bitmap - стандартный BMP файл. |
Formatted Memo F | ftFmtMemo | Форматированное поле Memo. |
OLE O | ftParadoxOle | Поле OLE для таблиц типа Paradox. |
| ftDBaseOle | Поле OLE для таблиц dBase. |
Binary B | ftTypedBinary | Типизированный бинарный формат. |
| ftCursor | Содержит образ курсора, выдаваемого хранимой процедурой данных Oracle. |
| ftFixedChar | Поле - одиночный символ. |
| ftWideString | Строка UNICODE-символов - wide chars. Аналогично типу WideString. |
Long Integer L | ftLargeInt | Написано LargeInt, читай long int. |
| ftADT | Поле абстрактного типа. |
| ftArray | Массив. |
| ftReference | Ссылка. |
| ftDataSet | Набор данных. |
| ftOraBlob | Большой Бинарный ОБъект для баз данных Oracle 7 и иже с ними. |
| ftOraClob | CLOB - тип для той же компании. |
| ftVariant | Вариантное поле. Его тип может динамически изменяться во время работы программы |
| ftInterface | Интерфейс. |
| ftIDispatch | Интерфейс IDispatch. |
| ftGuid | Стандартный GUID - универсальный OLE/COM идентификатор. |
^
1.9.Создание таблиц. Ключи и индексы
Поле - это ячейка в таблице. Запись - набор из полей. Существуют разные типы полей - обычные, индексные и ключевые. Обычные поля - просто данные. Индексное поле - поле, по которому данные сортируются. Ключевое - поле, значение которого уникально.
В общем-то четкого разделения нет. Ведь программа базы данных может сортировать таблицу и по обычным полям, а индексное поле может быть также уникальным.
В BDE достаточно логично поределена структура построения полей и их типов. Для этого имеются классы TxxxDef (три икса здесь обозначают подстановку, а то мало ли что Вы подумаете ;)), произведенные ото абстрактного базового класса TNamedItem. В компоненте TTable имеются и соответствующие свойства
- TIndexDefs
- TFieldDefs
Как и следовало предполагать, эти свойства содержат в себе определения индексных и обычных полей. Здесь нет свойства типа TKeyDefs, потому что в таблицах типа Парадокс индексные поля могут быть сами по себе уникальны. За счет этих свойств и задаются параметры таблицы, ее сетка. Создание таблицы довершает метод CreateTable.
Пример:
if (!Table1->Exists) // Проверка существования таблицы
{
Table1->Active = false; // Компонент TTable должен быть отключен.
// Опишем параметры таблицы.
Table1->DatabaseName = "BCDEMOS";//это по желанию
Table1->TableType = ttParadox; //тип таблицы - Парадокс.
Table1->TableName = "CustInfo";//имя создаваемой таблицы.
// Опишем поля и их типы.
Table1->FieldDefs->Clear();
TFieldDef *pNewDef = Table1->FieldDefs->AddFieldDef();
pNewDef->Name = "Field1";// имя, обычной строкой.
pNewDef->DataType = ftInteger;
//установим, является ли поле обязательным
pNewDef->Required = true;
//еще одно поле.
pNewDef = Table1->FieldDefs->AddFieldDef();
pNewDef->Name = "Field2";
pNewDef->DataType = ftString;
//определим размер поля.
pNewDef->Size = 30;
// Теперь взялись за индексы
Table1->IndexDefs->Clear();
/* Первый индекс безымянный, поскольку это основной индекс Парадокса. */
Table1->IndexDefs->Add("","Field1", TIndexOptions() <
Table1->IndexDefs->Add("Fld2Index","Field2", TIndexOptions() << ixCaseInsensitive);
// Ну и наконец, создаем таблицу.
Table1->CreateTable();
^
1.10.Класс TFieldDef.
Этот класс описывает поле, его тип и т.п. Свойства этого класса.
Attributes
Это свойство содержит аттрибуты данного поля. Это множество, состоящее из значений faHiddenCol, faReadonly, faRequired, faLink, faUnNamed, faFixed. Вот что они значат:
- faHiddenCol
Внутренний флаг, обозначающий, что столбец данных скрыт. Используется в динамических запросах к таблице.
- faReadOnly
Если этот флаг установлен, то редактирование данного поля запрещено.
- faRequired
Данное поле обязательно должно содержать установленное значение.
- faLink
Внутренний флаг для вложенных таблиц.
- faUnNamed
Только для внутреннего использования.
- faFixed
Обозначает, что поле имеет фиксированный размер.
ChildDefs
Это свойство и с ним связанные относятся не ко всем разновидностям (потомкам) класса TFieldDef, а только к производным TObjectField, например TADTField.
Определяет вложенные определения полей - дочерние поля. Это указатель на объект класса TFiledDefs. Для добавления вложеннных полей используется метод AddChild(void), возвращающий указатель на объект TFieldDef. Свойство ParentDef содержит указатель на родительское поле. Взаимосвязь - fDef = fDef->AddChild()->ParentDef. Метод HasChildDefs(void) возвращает, есть ли у данного поля вложенные.
DataType
Это свойство определяет реальный тип физического поля (того, которое записано в таблице или выдается по SQL запросу). Разные специализированные потомки TFieldDef автоматически проставляют значение этого свойсва. Пользователи, впрямую работающему с TFieldDef, приходится вручную устанавливать его значение.
FieldClass
Определяет метакласс поля, основываясь на значении DataType. Возвращается значение, к которому можно приравнять с помощью оператора __classid, например, fDef->DataType = ftInteger; fDef->FieldClass==__classid(TIntegerField);
InternalCalcField
Есть понятие RequestLive запроса, то есть запроса, который выдает динамически просчитываемые данные. Например, как в часто бывает на практике, есть поле ЦЕНА и поле КОЛИЧЕСТВО. Какое-либо поле типа ИТОГ не должно быть ведено отдельно и вводится отдельно. Это источник ошибок и вообще нерациональный метод ведения базы. Для этого есть запросы, например
^ SELECT ЦЕНА, КОЛИЧЕСТВО (ЦЕНА*КОЛИЧЕСТВО)
FROM DATA
Вот третье поле-то и будет ИТОГ. InternalCalcField как раз и определяет, является ли поле динамическим или нет. Это read-only property, его значение менять нельзя.
Required, Size
Своство Required определяет, обязательно ли поле должно иметь значение вообще. Свойство Size дает возможность установить или считать размер для поля. Тип поля должен быть следующий: ftString, ftBCD, ftBytes, ftVarBytes, ftBlob, ftMemo или ftGraphic.
Collection
Определяет указатель на содержащий данный объект (this) объект-список, коллекцию, производный абстрактного класса TCollection.
Это наиболее значимые свойства данного класса. Надо отметить, что обычно вместо этого класса используются более специализированные, например TADTFiled, TGraphicField, TStringField. Но основные свойства у них эти.
^
1.11.Коллекция TFieldDefs
Коллекция - в общем-то, специальный список с конкретизированными под данные нужды методами и свойствами. Вот TFieldDefs - коллекция для определений TFieldDef:
HiddenFields
Определеят, следует ли отображать дополнительные скрытые поля в запросе к базе данных. Преимущественно для внутреннего использования.
Items
Свойство типа массив, содержащее указатели на объекты типа TFieldDef.
ParentDef
Вроде мы уже это видели :). Определяет родительское (parent)поле. Логично :).
DataSet
Набор данных, использующий данную коллекцию. Я уже говорил, что по иерархии к DataSet относятся TTable и TDataSource.
Updated
Определяет, совпадают ли определения полей в реальном наборе данных и в данной коллекции.
Count
Количество полей.
Это были свойства. А теперь методы.
Add
Описание -
HIDESBASE void __fastcall Add(const AnsiString Name, TFieldType DataType, int Size, bool Required);
Параметр Name определяет имя для нового FieldDef, dataType тип поля, Size его размер, ну а Required - обязательно ли присвоение значения этому полю.
Пример использования - Table1->FieldDefs->Add("IntField",ftInteger,4,false);.
AddFieldDef
Описание -
TFieldDef* __fastcall AddFieldDef(void);
Этот метод возвращает указатель на новый объект типа TFieldDef, а потом уже можно с этим указателем делать все что угодно. Пример:
void TForm1::Example()
{
TFieldDef* def = Table1->FieldDefs->AddFieldDef();
def->DataType=ftString; //например
def->Size=20;
def->Required=true;//тоже например
}
Update
Описание -
HIDESBASE void __fastcall Update(void);
Обновляет записи в источнике данных (чаще всего таблице).
Find
Описание -
HIDESBASE TFieldDef* __fastcall Find(const AnsiString Name);
Производит поиск по коллекции, сравнивая значения Name полей. Как видно из описания, возвращает указатель на объект найденный. Если он не найден, то... Как это ни странно, возвращается не NULL, а чтобы определить, найден или нет, нужно вызвать метод IndexOf класса TDefCollection (предок TFieldDefs). О нем.
IndexOf
Описание -
int __fastcall IndexOf(const AnsiString AName);
Возвращает индекс данного объекта TFieldDef. Если нет такого, возвращается -1.
^
1.12.Изменение значений полей
А сейчас мы попробуем создать форму в стиле "Мастера форм" MS Access. В этом нам очень помогут компоненты с вкладки Data Controls, а именно TDBEdit, TDBComboBox, TDbCheckBox, TDBNavigator. После размещения всех элементов на форме получим следующее окно:
Теперь переходим к начинке системы. Бросаем объект TDataSource туда же. Выбираем все уже брошенные компоненты (кроме само собой TDataSource), и ставим их DataSource = DataSource1. Просто оценивая ситуацию поверхностным взглядом, ясно, что чего-то не хватает... А, нужно еще обозначить, к каким полям таблицы имеют отношение все элементы. Так как design-time таблицу мы подключить по ясным причинам (разные формы) не можем, то с клавиатуры впечатываем в свойства DataField компонентов имена соответствующих полей.
Реализуем свой просмотрщик в виде ^ MDI-приложения, как это делали ранее. Напомню, что для MDI приложения одно окно (главное) должно иметь FormStyle = fsMDIForm, а все остальные принадлежащие клиентской области этого окна окна должны иметь FormStyle = fsMDIChild. Настоятельно рекомендуется все формы, кроме главной, создавать динамически (вкладка Forms меню Project->Options). Функция создания окон должна выглядеть так:
TForm* TTextMain::AddChild(String fName,String caption)
{
TForm* child = NULL;
if(fName=="BOOKLIST")
child = new TBookList(this);
if(fName=="EDITBOOK")
child = new TEditBook(this);
if(!child)
{
child = new TTextView(this);
try
{
((TTextView*)child)->Output->Lines->LoadFromFile(fName);
}
catch(...)
{
delete child;
return 0;
}
}
Pages->Tabs->AddObject(caption,child);
Pages->TabIndex = Pages->Tabs->Count - 1;
child->Caption = caption;
child->Tag = Pages->Tabs->Count - 1;
return child;
}
В программе-просмотрщике окна подразделяются на несколько типов - список книг (^ TDBGrid), редактор элементов таблицы (созданный только что) и далее мы еще напишем список истории чтения. Соответственно fName - это имя файла с текстом книги. Если fName - некоторое предопределенное значение ("BOOKLIST" например), то создается вариант окна на эту тему, иначе открывается файл с книгой. Компонент TTabControl* Pages - некий суррогат панели задач, предоставляет быстрый доступ к окнам. Если все делалось правильно, то должна получится такого рода форма:
^
1.13.Проект приложения CView
Далее в разработке этого приложения созданим историю по принципу FIFO. Реализация представлена ниже:
void TTextHist::LoadHistory(String fName)
{
hist->Items->BeginUpdate();
hist->Clear();
dataset->DisableControls();
TListItem* itm = hist->Items->Add();
int p = dataset->RecNo;
dataset->First();
int cur = -1;
for(int i=0;iCount;i++)
{
dataset->RecNo = history->Names[i].ToInt();
cur = dataset->RecNo;
TListItem* itm = hist->Items->Add();
itm->Caption = dataset->Fields->Fields[1]->AsString;
itm->SubItems->Add(dataset->Fields->Fields[0]->AsString);
itm->SubItems->Add(dataset->Fields->Fields[2]->AsString);
itm->Data = (void*)cur;
}
dataset->RecNo = p;
dataset->EnableControls();
hist->Items->EndUpdate();
}
Формат файла истории hist.inf выглядит следующим образом:
;номер книги=позиция полосы прокрутки
23=100
Занесение в историю выполняется при добавлении очередного TextView.
TForm* TTextMain::AddChild(String fName,String caption,int id)
{
TForm* child = NULL;
if(fName=="BOOKLIST")
child = new TBookList(this);
if(fName=="EDITBOOK")
child = new TEditBook(this);
if(fName=="TEXTHIST")
child = new TTextHist(this);
if(!child)
{
for(int i=0;iClassName())=="TTextView")
if(((TTextView*)MDIChildren[i])->id==id)
{
BringWindowToTop(MDIChildren[i]->Handle);
return 0;
};
child = new TTextView(this);
try
{
((TTextView*)child)->Output->Lines->LoadFromFile(fName);
}
catch(...)
{
delete child;
return 0;
}
((TTextView*)child)->id = id;
int x = history->IndexOfName(id);
if(x!=-1)
{
history->Exchange(0,x);
SendMessage(((TTextView*)child)->Output->Handle,
EM_LINESCROLL,0,history->Values[id].ToInt());
}
else
{
history->Insert(0,String(id)+"=0");
if(history->Count>count)
history->Delete(count);
}
}
Pages->Tabs->AddObject(caption,child);
Pages->TabIndex = Pages->Tabs->Count - 1;
child->Caption = caption;
child->Tag = Pages->Tabs->Count - 1;
child->OnActivate = (TNotifyEvent)&ChildShow;
return child;
}
Принцип FIFO предполагает, что последний внесенный объект будет стоять на первом месте, а первый внесенный объект при этом удаляется.
Сохранение истории происходит при закрытии окна:
void __fastcall TTextMain::FormClose(TObject *Sender, TCloseAction &Action)
{
for(int i=0;iClassName())=="TTextView")
history->Values[((TTextView*)MDIChildren[i])->id] =
IntToStr(GetScrollPos(((TTextView*)MDIChildren[i])->Output->Handle,SB_VERT));
history->SaveToFile("hist.inf");
}
В данном случае перебором всех дочерних окон выбираются только относящиеся к типу TTextView. Для определения позиции полосы прокрутки используется стандартная WinAPI функция GetScrollPos.
^
1.14.Создание произвольной таблицы
Для создания таблицы используется метод CreateTable() компонента TTable (или любого другого аналогичного ему). Строго говоря, в таблице существуют простые поля и индексные. По индексным полям производится автоматическая сортировка. Предварительные описания полей содержатся в свойстве FieldDefs. В качестве примера создадим программу создающую произвольную таблицу . Форма ее будет такова:
Компонент TTable нужно настроить на конкретный алиас, используем ^ BCDEMOS. В TComboBox* FieldType и заполним все значения типов полей:
ftUnknown ftString ftSmallint ftInteger ftWord
ftBoolean ftFloat ftCurrency ftBCD ftDate
ftTime ftDateTime ftBytes ftVarBytes ftAutoInc
ftBlob ftMemo ftGraphic ftFmtMemo ftParadoxOle
ftDBaseOle ftTypedBinary ftCursor ftFixedChar
ftWideString ftLargeint ftADT ftArray ftReference
ftDataSet ftOraBlob ftOraClob ftVariant ftInterface
ftIDispatch ftGuid ftTimeStamp ftFMTBcd
Очень важным является соблюдения порядка, соответствующего enum TFieldType. Затем пишем код:
//---------------------------------------
void __fastcall TForm1::AddDefClick(TObject *Sender)
{
ListBox->Enabled = false;
AddBox->Enabled = true;
}
//---------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
table->FieldDefs->Clear();
}
//---------------------------------------
void __fastcall TForm1::AddFieldClick(TObject *Sender)
{
TFieldDef* def = table->FieldDefs->AddFieldDef();
def->Name = FieldName->Text;
def->Size = FieldSize->Text.ToInt();
def->DataType = (TFieldType)FieldType->ItemIndex;
def->Attributes << (TFieldAttribute)((faHiddenCol&FieldHidden->Checked)|
(faRequired&FieldRequired->Checked)|
(faReadonly&FieldReadOnly->Checked)|
(faFixed&FieldFixed->Checked));
Fields->Items->AddObject(FieldName->Text,def);
Fields->ItemIndex = Fields->Items->Count - 1;
CancelFieldClick(0);
}
//---------------------------------------
void __fastcall TForm1::CancelFieldClick(TObject *Sender)
{
ListBox->Enabled = true;
AddBox->Enabled = false;
}
//---------------------------------------
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
for(int i=0;i
((TFieldDef*)Fields->Items->Objects[i])->FieldNo = i;
table->TableType = (TTableType)TableType->ItemIndex;
table->TableName = TableName->Text;
table->CreateTable();
}
//---------------------------------------
void __fastcall TForm1::RemoveDefClick(TObject *Sender)
{
table->Active = false;
if(Fields->ItemIndex==-1)return;
TFieldDef* def = (TFieldDef*)Fields->Items->Objects[Fields->ItemIndex];
table->FieldDefs->Delete(def->Index);
Fields->DeleteSelected();
}
//---------------------------------------
void __fastcall TForm1::FieldsChange(TObject *Sender)
{
TFieldDef* def = (TFieldDef*)Fields->Items->Objects[Fields->ItemIndex];
FieldSize->Text = def->Size;
FieldType->ItemIndex = def->DataType;
FieldName->Text = def->Name;
FieldHidden->Checked = def->Attributes.Contains(faHiddenCol);
FieldRequired->Checked = def->Attributes.Contains(faRequired);
FieldReadOnly->Checked = def->Attributes.Contains(faReadonly);
FieldFixed->Checked = def->Attributes.Contains(faFixed);
}