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

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

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

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

void __fastcall TForm1::ListBox1EndDrag(TObject *Sender, TObject *Target, int X, int Y)

{

Label1->Caption = "Завершение перетаскивания...";

}

Скомпилируйте и запустите приложение. Выбирая элементы в списке, следите за текстом метки в нижней части формы. Заметьте, что просто выбор элемента и его перемещение начинает процесс перетаскивания. Процесс заканчивается, когда кнопка мыши где-либо отпускается. Если даже курсор мыши находится над тем же списком, вызывается событие OnEndDrag.

Теперь вы знаете достаточно о drag-and-drop в системе CBuilder, чтобы быть опасным. Пример drag-and-drop в списках показал вам, как делать некоторые вещи, но не до конца. Нужно сделать еще парочку улучшений.

Списки с drag-and-drop, часть вторая

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

Во второй версии программы перетаскивания в списках мы решим эту проблему.

Замечание

Исходный код для второго примера программы перетаскивания в списках находится на сопроводительном компакт-диске в каталоге Chapter4\DragDropList2.

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

void __fastcall TForm1::OnDragDrop(TObject *Sender, TObject *Source, int X, int Y)

{

TListBox *pList1 = (TListBox *)Source; TListBox *pList2 = (TListBox *)Sender;

//Какой элемент находится под перетаскиваемыми? POINT p;

p.x = X; p.y = Y;

int nItemIndex = pList2->ItemAtPos( p, false );

String s = "Роняем на элемент: " + String(nItemIndex); Label1->Caption = s;

//Копируем то, что выбрано

for ( int i=0; i<pList1->Items->Count; ++i ) if ( pList1->Selected[ i ] )

{

// Добавить во второй список

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

pList2->Items->Insert( nItemIndex, pList1->Items->Strings[ i ] );

// И удалить из первого pList1->Items->Delete( i );

}

}

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

Заметьте, что мы добавили кусочек кода, отмечающий место, куда элемент попадает. Причина этого проста. Попробуйте перетащить элемент ниже последнего элемента в списке. Вы можете предположить, что метод ItemAtPos сойдет с ума, пытаясь определить, что за элемент лежит в позиции, не принадлежащей ни одному элементу. Конечно, я тоже этого ожидал, когда писал этот пример, но метод с ума не сошел. На самом деле, он работает именно так, как я бы хотел, возвращая номер на один больше, чем число элементов в списке. Это замечательно работает с методом Insert (вставить) свойства Items (элементы), принадлежащего классу TListBox (список), который, получив этот номер, радостно добавит элемент к концу списка. Хм. Похоже, кто-то уже действительно думал над этой проблемой.

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

Итак, вы теперь знаете намного больше о процедуре drag-and-drop, чем раньше, может даже больше, чем вам хотелось.

Карты сообщений и CBuilder

Windows — система, построенная на сообщениях (messages). Сообщения посылаются системой Windows приложениях для информирования их об изменениях состояния, изменениях в среде, действиях пользователя, а также для информирования о том, что какое-то действие приложению необходимо выполнить.

С другой стороны, CBuilder — система, основанная на событиях (events). События генерируются компонентами VCL и системой и передаются в формы приложения и другие объекты через обработчики событий. Эти обработчики вызываются с информацией, необходимой приложению для понимания, что же происходит. Очень многие сообщения Windows завернуты в обложку события в CBuilder. Например, когда система Windows генерирует сообщение LBN_SELCHANGE, которое информирует приложение о том, что пользователь сделал изменения выбора элементов в списке, объект библиотеки VCL TListBox (список) в CBuilder генерирует событие SelectionChange для владельца списка. Добавление обработчика события SelectionChange — все, что нужно для обработки низлежащего сообщения Windows LBN_SELCHANGE.

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

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

Иногда вам понадобится обрабатывать сообщения, для которых нет соответствующего события в объекте VCL, к которому сообщение относится. Замечательный пример этого объект TForm и сообщение WM_VSCROLL. Сообщение WM_VSCROLL посылается форме, когда происходит щелчок на полосе прокрутки (scrollbar) формы (которая является частью самой формы) в том или ином месте. Есть несколько случаев, когда генерируется это сообщение. Когда пользователь нажимает стрелку вниз или стрелку вверх на полосе прокрутки, сообщение генерируется с кодом SB_LINEUP (для стрелки вверх) и SB_LINEDOWN (для стрелки вниз). Также сообщение посылается с кодом SB_PAGEUP, когда щелчок происходит на самой полосе прокрутки выше указательной кнопки. Есть также много других примеров таких кодов.

Дело, однако, в том, что вы не можете поймать сообщения прокрутки в форме через обработчики событий. Если вы посмотрите на список определенных для класса VCL TForm событий, вы не найдете там событий OnLineUp или OnPageDown. Если вы хотите определить такие события самостоятельно, то вам придется создавать новый компонент, наследующий от TForm (нетривиальное упражнение) и затем специально проверять на сообщение в компоненте или найти какую-нибудь дыру в системе, чтобы сделать сообщения полосы прокрутки доступными для вас, программиста. Или вы можете использовать карты сообщений.

Карты сообщений очень хорошо знакомы программистам на Borland C++/OWL или Visual C++/MFC, они используются каркасными системами для работы с сообщениями. Вы пишите функцию, присоединяете ее к позиции в карте сообщений, соответствующей нужному сообщению, и ждете, пока система не вызовет функцию в ответ на это сообщение. Карты сообщений далеко не так элегантны, как обработчики событий, хотя они и работают. Гораздо труднее, на самом деле почти невозможно переключать обработчики сообщений во время работы приложения в том виде, в каком это можно сделать для обработчиков событий. Перед тем, как систему карты сообщений, серьезно подумайте, нужно ли вам это.

Ладно, все сказано, так далеко вы вряд ли стали бы читать, если бы у вас не было к тому причины. Карты сообщений действительно позволяют программисту на CBuilder решать некоторые проблемы, которые иначе решить невозможно. Сравните это с программистами на Visual Basic, имеющими в активе сообщения, которые позволяет обрабатывать эта система, и никаких других. Программистам на Visual Basic частенько приходится прибегать к посторонним компонентам, например Message Blaster VBX, для того, чтобы обрабатывать сообщения, не определенные внутри Visual Basic. До версии Visual Basic 5.0, по сути, вы не могли определить функцию типа callback для сообщений. Может, CBuilder и не идеал, но это заметный шаг вперед в соревновании в данной области.

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

Реализация карт сообщений

На рис. 4.9 представлена форма, которая покажет мощь системы карт сообщений в CBuilder. Для создания этой формы добавьте панель состояния в верхнюю часть формы, установив свойство Alignment (выравнивание) панели состояния в alTop. Это заставит панель состояния «отъесть» часть пространства формы и урежет клиентскую область формы. Это необходимо, так как если мы разместим панель состояния внизу, то при вертикальной прокрутке формы (чем мы собираемся заниматься) панель состояния будет находится на дне виртуальной формы, то есть довольно далеко. Сейчас панель состояния будет видна всегда, и ее можно использовать для отображения информации о текущем состоянии формы.

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

Рис. 4.9. Форма примера карт сообщений

Позаботившись о панели состояния, следующим шагом нам надо установить полосы прокрутки у формы, чтобы мы могли получать от них данные. Чтобы заставить форму отображать полосы прокрутки, выберите форму в Object Inspector. Найдите свойство VertScrollBar (вертикальная полоса прокрутки) и щелкните дважды в левой части таблицы Object Inspector. Это раскроет свойство для показа подсвойств. Поменяйте подсвойство Range (диапазон) на 1000; этого достаточно, чтобы полоса прокрутки появилась.

Перейдите к свойству HorzScrollBar (горизонтальная полоса прокрутки) и повторите операцию. Когда вы закончите, у формы появятся обе полосы прокрутки вертикальная и горизонтальная. Теперь перейдите к панели состояния и щелкните справа от свойства Panels (секции). Мы

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

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

Общий синтаксис карты сообщений таков:

BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(message, function)

END_MESSAGE_MAP(object)

где message — сообщение Windows, которое вы хотите обработать. Обычно сообщения Windows выглядят примерно так: WM_xxx; function — функция на уровне объекта, которую вы хотите использовать для обработки сообщения. Функции, обрабатывающие сообщения, обычно имеют один параметр ссылку на объект типа TMessage; object — класс, для которого вы определяете эту карту сообщений (TForm, TListBox, ...).

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

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

//----------------------------------------------------------

#ifndef Unit1H #define Unit1H

//----------------------------------------------------------

#include <vcl\Classes.hpp> #include <vcl\Controls.hpp> #include <vcl\StdCtrls.hpp> #include <vcl\Forms.hpp> #include <vcl\ComCtrls.hpp>

//----------------------------------------------------------

class TForm1 : public TForm

{

__published: // IDE-managed Components TStatusBar *StatusBar1;

void __fastcall HandlePaint(TObject *Sender); private: // User declarations

void __fastcall HandleVScroll(TMessage& Msg); void __fastcall HandleHScroll(TMessage& Msg); int FnStartLine;

int FnStartCol;

public: // User declarations

__fastcall TForm1(TComponent* Owner); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_VSCROLL,HandleVScroll) MESSAGE_HANDLER(WM_HSCROLL,HandleHScroll)

//Можете добавить сюда

//любое количество дополнительных обработчиков

END_MESSAGE_MAP(TForm) };

//-----------------------------------------------------------

extern TForm1 *Form1; //-----------------------------------------------------------

#endif

Первая часть исправлений объявляет два метода (HandleVScroll и HandleHScroll), которые мы будем использовать как обработчики сообщений в этой форме. Оба метода принимают по одному параметру ссылке на объект типа TMessage, который содержит входную информацию о сообщении. Заметьте, что так как это обработчики сообщений и поэтому перекрывают обработчики в низлежащей VCL, то нужно использовать для этих методом модификатор __fastcall.

Переменные FnStartLine и FnStartCol (члены класса TForm1) будут использованы для хранения того, насколько далеко мы прокрутили форму соответственно в вертикальном и горизонтальном направлении. Также эти переменные будут использоваться для отображения информации в панели состояния и для определения того, что будет прорисовано на форме.

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

Обычно вы обрабатываете прокрутку формы, потому что вы хотите управлять прорисовкой текста, графики или других данных на форме. Для этого мы переопределим прорисовку формы, добавив обработчик события OnPaint. В Object Inspector добавьте обработчик события OnPaint и дайте ему имя HandlePaint. Перейдите в редактор и добавьте в обработчик события HandlePaint следующий код:

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

void __fastcall TForm1::HandlePaint(TObject *Sender)

{

int x = 0; int y = 0;

for ( int i=FnStartLine; i<100; ++i)

{

String s = "Это строка " + String(i); int nHeight = Canvas->TextHeight( s ); Canvas->TextOut( x, y, s);

y += Height;

}

}

Как видите, мы просто отображаем строки текста на рабочем пространстве формы. Строки текста отображают номер строки, начиная с текущей стартовой строки и увеличиваясь до 100 отображенных строк. Каждая строка текста будет изображена на отдельной строке формы, так как мы увеличиваем вертикальную (y) координату на высоту предыдущей строки.

Добавляем обработчик вертикальной прокрутки

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

void __fastcall TForm1:HandleVScroll(TMessage& Msg)

{

int nStartPos = FnStartLine;

switch( Msg.WParam )

{

case SB_LINEUP: if ( FnStartLine ) FnStartLine--; break;

case SB_LINEDOWN: FnStartLine++; break;

case SB_PAGEDOWN: FnStartLine += 10; break;

case SB_PAGEUP:

if ( FnStartLine < 10 ) FnStartLine = 0; else

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

FnStartLine —= 10; break;

}

// Если позиция изменилась, перерисовывать! if ( FnStartLine != nStartPos)

Invalidate();

StatusBar1->Panels->Items[0]->Text =

"Ряд: " + String(FnStartLine);

StatusBar1->Panels->Items[1]->Text =

"Кол: " + String(FnStartCol);

}

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

Обработка горизонтальной прокрутки

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

void __fastcall TForm1:HandleHScroll(TMessage& Msg)

{

int nStartPos = FnStartCol;

switch( Msg.WParam )

{

case SB_LINEUP: if ( FnStartCol ) FnStartCol--; break;

case SB_LINEDOWN: FnStartCol++; break;

case SB_PAGEDOWN: FnStartCol += 10; break;

case SB_PAGEUP: if ( FnStartCol < 10 ) FnStartCol = 0; else

FnStartCol —= 10;

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

break;

}

StatusBar1->Panels->Items[0]->Text =

"Ряд: " + String(FnStartLine);

StatusBar1->Panels->Items[1]->Text =

"Кол: " + String(FnStartCol);

}

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

__fastcall TForm1::TForm1(TComponent *Owner) : TForm(Owner)

{

FnStartLine = 0;

FnStartCol = 0;

}

Вот и все относительно этого примера карт сообщений. Как видите, обработка карт сообщений не особо сложна. Вы просто добавляете элементы в карту, точно так же, как вы бы это делали в Visual C++ или Borland C++. В CBuilder нет встроенной поддержки автоматического добавления элементов в карту сообщений, в основном потому, что добавление элемента в карту сообщений должно быть последним прибежищем отчаявшихся, а не первым шагом, как это происходит в каркасных системах.

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

Создание списка, прорисовываемого его владельцем

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

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

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

Понятие о списках, прорисовываемых владельцем

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

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

Для реализации owner-draw списка вам нужно понимать кое-что о сообщения Windows, которые посылаются за кулисами деятельности списка. При создании такого списка два сообщения Windows имеют первостепенную роль. К счастью, VCL обрабатывает эти сообщения в события, так что вы можете работать через стандартную обработку событий. Нет необходимости возиться с элементами карты сообщений при работе с owner-draw списками в CBuilder.

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

Второе сообщение, которое нужно обрабатывать — WM_DRAWITEM. Это сообщение, которое транслируется в событие DrawItem, нужно Windows для самой прорисовки каждого элемента в списке. Когда Windows определяет, что элемент должен быть перерисован на поверхности списка, то для этого элемента вызывается обработчик события DrawItem. Обработчик будет вызываться неоднократно, при каждой перерисовке элемента. В отличие от других систем, VCL большую часть owner-draw списка рисует сама, так что вам достаточно реализовать части, уникальные в вашей форме приложения.

Эти два сообщения единственные, о которых надо позаботиться при создании owner-draw списков. Задача в их грамотном использовании. Хотя это и не слишком трудная проблема, обычно проще, чтобы вам кто-то показал, как это делается, а потом вы бы копировали этот код в другие приложения. Такое отношение очень важно в CBuilder, и мы его будем использовать где только можно. Не изобретайте колесо, если кто-то уже сделал работу за вас. Вы увидите, что хотя вы и вольны творить что угодно, но все получается быстрее и проще, когда вы основываетесь на уже написанных, протестированных компонентах в системе, чем когда вы большую часть работы делаете сами.

Реализация примера

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

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

Замечание

Исходный код для программы «Ручная прорисовка списков» находится на сопроводительном компакт-диске в каталоге Chapter4\OwnerDrawList.

Форма, с которой мы будем работать в этом приложении, приведена на рис. 4.10. Создайте простую форму и положите на нее список (list box), более-менее отцентрировав его на форме. Кроме списка, мы будет работать с FontDialog (диалог установки шрифта) и ColorDialog (диалог установки цвета), а также с главным меню. Добавьте все эти компоненты на форму в любом месте. Не забудьте поставить стиль списка в Owner-Draw Variable (переменной высоты с ручной прорисовкой), иначе код, который мы напишем в этом примере, не будет правильно работать. Если вы напишите весь этот код и в списке ничего правильного не окажется (только текст), то проверьте значение этого свойства у списка.

Рис. 4.10. Форма примера ручной прорисовки списка

Модификация заголовочного файла

В заголовочный файл (Unit1.h) нашего приложения нужно внести несколько изменений перед тем, как продолжить работу над примером. Эти изменения приведены в следующем листинге. Изменения, которые вам нужно сделать, выделены подсветкой:

//--------------------------------------------------------

#ifndef Unit1H #define Unit1H

//--------------------------------------------------------

#include <vcl\Classes.hpp> #include <vcl\Controls.hpp> #include <vcl\StdCtrls.hpp> #include <vcl\Forms.hpp> #include <vcl\Dialogs.hpp> #include <vcl\Menus.hpp>

//--------------------------------------------------------

class TForm1 : public TForm

{

__published: // IDE-managed Components TListBox *ListBox1;

TFontDialog *FontDialog1;

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