Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Все компоненты объединены в библиотеку VCL и расположены на Палитре компонентов. Если компонент перенесен на форму, то в Инспекторе объектов можно редактировать его свойства и создавать обработчики событий.
Предком для всех классов библиотеки VCL служит класс TObject. Этот класс содержит методы, которые вы можете найти во всех его потомках.
Объект типа TObject передается в качестве параметра в обработчики событий.
Например, если вы разместите на форме кнопку, и затем сделаете на ней двойной щелчок для создания обработчика OnClick, то увидите заготовку для функции-обработчика:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
<Здесь будем писать код обработчика>
}
Кнопка является, наверное, самым распространенным элементом пользовательского интерфейса. В C++ Builder'е существует несколько видов кнопок. Самая простая кнопка - это компонент Button:
Чтобы создать обработчик щелчка по кнопке, нужно добавить в него нужный код. Например, для кнопки закрытия приложения:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Close();
}
У кнопки есть много полезных свойств. Например, для того, чтобы кнопка оставалась всегда у правого края формы при изменении размеров последней, достаточно у свойства Anchors (привязки) поменять два подсвойства - подсвойство akLeft установить в false, а akRight - в true:
Теперь при изменении размеров формы кнопка останется «привязанной» к её правому нижнему краю.
Следующий тип кнопки - это BitBtn (вкладка Additional):
Эта кнопка представляет из себя кнопку с картинками, причем картинку вы можете использовать как свою, так и предопределенную (для значений OK, Cancel, No и других).
Для использования одной из стандартных картинок вы должны задать свойство Kind. Примеры возможных значений для этого свойства - bkCancel, bkNo, bkAbort. Вот так, например, будет выглядеть наша кнопка со свойством Kind равным bkAbort:
Обратите внимание, что надпись на кнопке (свойство Caption) при этом автоматически установилось в Abort (но его, разумеется, можно поменять).
Если же мы хотим задать нашу картинку для кнопки, то свойство Kind мы устанавливаем в bkCustom (значение по умолчанию), а нужную картинку загружаем в свойстве Glyph. После этого наша кнопка может выглядеть так:
За то, как наша картинка расположена относительно надписи на кнопке, отвечает свойство Layout. Возможные значения для него - blGlyphLeft (по умолчанию), blGlyphRight, blGlyphBottom и blGlyphTop.
Компонент Edit предназначен для ввода или вывода текста. Расположен он на вкладке Standard Палитры компонентов:
Основное его свойство - это Text. Оно позволяет читать и записывать некоторый текст в Edit. Обратите внимание, что это свойство имеет тип AnsiString, поэтому для преобразования строки в число нужно использовать функцию:
int a = StrToInt(Edit1->Text);
Кроме функции StrToInt() есть обратная к ней IntToStr(). Они переводят строку в целое число и целое число в строку соответственно. Кроме этой пары функций имеется пара StrToFloat() и FloatToStr(), котрые работают с вещественными числами, а также FloatToStrF(), позволяющая задать формат вывода числа.
После каждого изменения содержимого текста возникает событие Change, поэтому при необходимости можно написать обработчик данного события. Кроме того, часто используются такие события как KeyPress (возникает при вводе каждого символа), KeyDown и KeyUp (возникают при нажатии и отпускании клавиши). Так, например, можно ограничить пользовательский ввод только символами из некоторого набора:
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
if (Key!='a' && Key!='b' && Key!='c')
{
Key=0; //Обнуляем символ, отменяя реакцию на его ввод
}
}
В этом примере пользователь сможет ввести только символы a, b и c.
Пояснения. 1. Параметр Key передается по ссылке, что и позволяет нам
изменить его.
2. Событие KeyPress возникает при нажатии алфавитно-
цифровых клавиш. Если нужно отследить нажатие других
клавиш (например, F1, Alt, Ctrl и Shift или клавиш со
стрелочками), то используйте события KeyDown и KeyUp.
Из полезных свойств компонента TEdit отметим еще некоторые.
Свойство CharCase. Возможные значения для него - ecNormal (вводимый текст автоматически не преобразуется), ecLowerCase (текст преобразуется к нижнему регистру) и ecUpperCase (текст преобразуется к верхнему регистру).
Свойство MaxLenght. Задает максимально возможное число символов. По умолчанию равно нулю, что означает, что количество вводимых символов не ограничено.
Свойство ParentFont. Может принимать значение true (будет использоваться шрифт формы) и false (будет использоваться собственный шрифт).
Свойство PasswordChar. Позволяет задать символ-заменитель для ввода пароля. Чаще всего для этих целей используют звездочку. Свойство text при этом все равно будет содержать вводимый пользователем пароль.
Компонент Label (метка) расположен на вкладке Standard Палитры Компонентов:
Перечислим его основные свойства. Самое важное из них - это, несомненно, свойство Caption. Именно оно определяет, что за надпись будет иметь наша метка.
Следующее свойство - это AutoSize логического типа. По умолчанию оно равно true, и наша метка будет автоматически увеличивать свои размеры, если текст, задаваемый свойством Caption, будет достаточно длинным.
Свойство WordWrap определяет, происходит ли перенос длинных строк. Если это свойство установить в true, то длинная строка разобьется на несколько. При этом свойство AutoSize должно быть установлено в false.
Для цветов служат свойства Color (цвет фона) и подсвойство Color свойства Font (задает цвет шрифта). Первому из них (для цвета фона) рекомендуется задавать значение clBtnFace. В этом случае цвет фона для надписи будет сливаться с цветом формы.
Для задания шрифта используется составное свойство Font. У него есть ряд подсвойств: Size (размер), Style (задает такие характеристики как курсив или подчеркнутость). Подсвойства свойства Font можно задавать как на этапе разработки программы, так и во время её работы:
Label1->Font->Size=16; //Задаем новый размер
//Задаем полужирность и подчекнутость шрифта
Label1->Font->Style = TFontStyles()<< fsBold << fsUnderline;
Компонент StaticText расположен на вкладке Additional Палитры Компонентов:
Его свойства совпадают, в основном, со свойствами Label. Самое существенное различие между этими двумя компонентами в том, что Label - это не оконный элемент, а StaticText - оконный (т. е. имеет свой дескриптор окна: hWnd).
Если компоненты Label или StaticText должны отображать значения числовых переменных, то следует воспользоваться функциями IntToStr() и FloatToStr().
Компонент ListBox (список строк) расположен на вкладке Standard:
Он позволяет добавление новых строк, их удаление, поиск нужной строки, очистка всего ListBox'а и др. Строки для нашего ListBox'а хранятся в его свойстве Items. Для задания этого свойства на этапе разработки щелкните на многоточии рядом с ним в Инспекторе объектов:
Появится диалоговое окно String List Editor, в котором можно ввести элементы списка:
Если же вам надо добавить новый пункт на этапе работы программы, то надо воспользоваться методом Add упомянутого свойства Items:
ListBox1->Items->Add("New String");
Этот метод добавит новый элемент в конец списка. Если же нам надо добавить новый элемент куда-нибудь в середину, то используем метод Insert:
ListBox1->Items->Insert(1,"Roma");
Для очистки всего списка вызываем метод Clear:
ListBox1->Items->Clear();
Если нам надо удалить i-й элемент ListBox'а, то мы используем метод Delete (нумерация элементов списка идет с нуля):
ListBox1->Items->Delete(i);
Определить выделенный элемент списка позволяет свойство ItemIndex. Оно представляет из себя номер выделенного элемента. Если ни один элемент не выделен, то это свойство равно -1. Вот так, например, будет выглядеть код, который при щелчке на ListBox'е покажет в MessageBox'е номер элемента, на котором был произведен щелчок:
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
ShowMessage(IntToStr(ListBox1->ItemIndex));
}
Если вам надо, чтобы в ListBox'е пользователь имел возможность выделить сразу несколько элементов, то установите свойство MultiSelect в true (по умолчанию оно равно false).
Доступ к определенной строке можно получить через ее индекс (нумерация, как всегда, идет с нуля):
ListBox1->Items->Strings[0];
Для добавления строки служит метод Add:
ListBox1->Items->Add("Вася");
Для вставки строки в определенное место служит метод Insert:
ListBox1->Items->Insert(1,"Петя");
Свойство Count возвращает количество строк в списке:
int k = ListBox1->Items->Count;
Метод Clear предназначен для удаления всех строк из компонента:
ListBox1->Items->Clear();
Для удаления же отдельного элемента с номером k служит метод Delete:
ListBox1->Items->Delete(k);
Для поиска определенной строки служит метод IndexOf:
int k = ListBox1->Items->IndexOf("Петя");
Этот метод берет в качестве параметра искомую строку и возвращает ее номер. Если строка не найдена, то возвращается -1.
Компонент ComboBox (выпадающий список) расположен на вкладке Standard Палитры Компонентов:
Этот компонент по своим свойствам очень похож на компонент ListBox. Методы и свойства он имеет почти те же самые. Самое важное из них - это свойство Items. Именно в нем и хранятся все строки ComboBox'а. Из отличных от ListBox'а свойств выделим свойство Text. Оно дает нам текст в нашем ComboBox'е (т.е. то, что пользователь непосредственно видит). Вот так, например, можно добавить напечатанный пользователем текст в ComboBox:
ComboBox1->Items->Add(ComboBox1->Text);
Из полезных свойств отметим еще свойство Style. Возможные значения для него - csDropDown (ComboBox с возможностью редактирования), csDropDownList (ComboBox без возможности редактирования, т. е. пользователь может выбирать только из существующих элементов), csSimple и другие. При значении style равным csSimple ComboBox будет выглядеть приблизительно так:
Компонент CheckBox располагается на вкладке Standard:
Этот компонент играет роль флажка и предназначен для включения/выключения некоторого параметра. Для него основное свойство - это State. Именно оно и отвечает за внешний вид нашего CheckBox'а. Это свойство может принимать одно из трех значений: cbChecked (галочка стоит), cbUnchecked (галочка не стоит) и cbGrayed (CheckBox находится в неопределенном состоянии).
Обратите внимение, что у CheckBox'а может быть именно три состояния. Третье состояние CheckBox может иметь, например, при показе стиля выделенного текста в некотором текстовом редакторе - если часть текста, например, подчеркнута, а часть нет, то логично, чтобы CheckBox имел стиль cbGrayed. Вот так будет выглядеть CheckBox с состоянием cbGrayed:
Если щелкать на компоненте, то он будет менять два своих состояния (с галочкой и без). Если же мы хотим, чтобы при щелчке он циклически менял три своих состояния, то необходимо установить его свойство AllowGrayed в true.
Состояние компонента можно получить через его свойство Checked логического типа. Если оно равно true, то TCheckBox отмечен, если false - то не отмечен.
За надпись, расположенную рядом с квадратиком, отвечает свойство Caption.
Основное событие для компонента CheckBox - это OnClick. Оно, естественно, возникает при щелчке. Для добавления заготовки обработчика для этого события достаточно просто сделать на CheckBox'е двойной щелчок. Вот так, например, можно в заголовок формы вывести информацию о состоянии CheckBox'а:
void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
if(CheckBox1->Checked) Form1->Caption="Включено";
else Form1->Caption="Выключено";
}
Компонент RadioGroup расположен на вкладке Standard:
Этот компонент позволяет выбрать один вариант из нескольких. Список выбора создается в редакторе свойства Items, где текст каждой строки будет названием пункта:
Если также задать пункт, выбранный по умолчанию (свойство ItemIndex = 0), и название Caption «Вариант», то на форме это будет выглядеть так:
Теперь можно в любом месте программы проверять, в каком положении находится
переключатель, и выполнять разные группы операторов :
switch(RadioGroup1->ItemIndex)
{
case 0: <действия-1> ; break;
case 1: <действия-2> ; break;
case 2: <действия-3> ; break;
}
Здесь мы не используем метод компонента OnClick(), хотя выбор действий можно выполнить и в этом обработчике.
Класс TStringList предназначен для хранения набора строк и является невизуальным. Он является непосредственным потомком класса TStrings и наследует все методы и свойства своего родителя.
В отличие от своего родителя, класс TStringList позволяет создавать свои экземпляры.
Кроме того, этот класс имеет собственные свойства и методы, самые важные из которых перечислены ниже:
Свойство Sorted логического типа. Если установлено в true, то список автоматически сортируется, если false, то не сортируется. Пример использования:
TStringList *s=new TStringList;
s->Sorted=true;
s->Add("Роман");
s->Add("Вася");
s->Add("Петя");
ListBox1->Items->AddStrings(s); // Показываем сортированный список
delete s; // Удаляем объект
Свойство Duplicates. Свойство перечисляемого типа, если установлено в dupIgnore, то добавить повторяющуюся стороку нельзя (но при этом старые повторяющиеся строки сохраняются), dupAccept - можно добавлять повторяющиеся строки, dupError - при попытке добавить повторяющуюся строку генерируется ошибка EStringListError. Это свойство игнорируется, если список не отсортирован.
Свойство CaseSensitive. Свойство логического типа, определяющее, учитывается ли при сортировке регистр (true - учитывается, false - не учитывается).
Метод Sort. Также сортирует список:
TStringList *s=new TStringList;
s->Add("Роман");
s->Add("Вася");
s->Add("Петя");
s->Sort();
ListBox1->Items->AddStrings(s); // Показываем сортированный список
delete s; // Удаляем объект
Компонент ImageList предназначен для хранения набора однотипных изображений и
расположен на вкладке Win32. Конечно, изображения можно хранить и по отдельности - но в наборе удобнее. ImageList можно рассматривать как массив изображений - в частности, к элементам такого набора вы можете обращаться по индексу.
Перенесите его на форму. Сейчас в нашем ImageList изображений нет. Давайте добавим несколько изображений. Для этого сделайте двойной щелчок на расположенном на форме компоненте ImageList1. Появится диалоговое окно для работы с изображениями.
Естественно, что для добавления изображения используется кнопка Add. При нажатии на нее появляется стандартное окно для выбора файла. Выберите какой-нибудь bmp-файл с изображением размера 32 на 16. Естественно, что такой файл надо предварительно создать. В файле должно быть 2 изображения 16 на 16. Нажмите на кнопку Open. Так как у нас 2 изображения, то должно появится окно с вопросом, предлагающим разделить нашу картинку на две (на две, так как картинки должны быть квадратные). Отвечаем, естественно, да:
Теперь в нашем диалоговом окне появилось 2 изображения:
Назначение остальных кнопок понятно. Отметим все же, что удалять можно и отдельные изображения из загруженного файла - т. е. фактически из графического файла можно взять только нужные картинки.
Изображения в диалоговом окне можно менять местами (перетаскиванием мышью).
Закройте диалоговое окно. Давайте теперь используем наш ImageList. Добавьте на форму компонент Image с вкладки Additional Палитры компонентов и обычную кнопку. В обработчик для щелчка по кнопке внесите следующий код:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
static int index=0;
//Выводим очередное изображение в Image1.
ImageList1->GetBitmap(index, Image1->Picture->Bitmap);
index++; //Берем индекс следующей картинки.
Invalidate(); //Перерисовываем.
}
Теперь если вы запустите программу и будете щелкать на кнопке, то в Image1 будут последовательно появляться изображения из ImageList1 - сначала с индексом 0, потом с индексом 1 и т. д. В приведенном фрагменте используется метод GetBitmap класса TImageList. Первым параметром он берет номер картинки из ImageList (нумерация идет с нуля), вторым - куда эта картинка пишется. У нас она пишется в Image1.
Вообще говоря, довольно-таки много компонентов имеют свойство Images. Это свойство как раз и имеет тип ImageList. Например, если вы разместите на форме компонент MainMenu, то для этого свойства вы сможете выбрать все ImageList'ы:
Для отдельных же пунктов меню вы можете выбирать изображения из ImageList по индексу.
OpenDialog
Часто в программах используют стандартные диалоги для открытия и сохранения файлов соответственно. Для этого нужно разместите на форме компоненты OpenDialog и SaveDialog (с вкладки Dialogs):
Код может быть таким (читаем данные из файла):
if(OpenDialog1->Execute())
Memo1->Lines->LoadFromToFile(SaveDialog1->FileName);
или таким (пишем данные в файл):
if(SaveDialog1->Execute())
Memo1->Lines->SaveToFile(SaveDialog1->FileName);
Компонент MainMenu расположен на вкладке Standard Палитры компонентов:
Перенесите компонент на форму. Где он будет располагаться - неважно, при запуске программы наше меню все равно будет там, где ему и положено быть - вверху формы.
Для добавления пунктов в меню сделайте двойной щелчок на компоненте. Откроется форма, в которой вы сможете создать пункты визуальным образом. Для этого надо просто напечатать заголовок в пустом прямоугольнике. Заголовок - это свойство Caption для нашего пункта меню (это видно в окне Инспектора объектов). Если щелкнуть мышкой на прямоугольнике с пунктом меню, то появятся два новых пустых прямоугольника - снизу и справа:
В эти прямоугольники можно напечатать очередные пункты нашего меню.
Часто у подпунктов меню есть свои подпункты. Для создания такого подпункта щелкните правой кнопкой мыши на нужном пункте меню и в контектном меню выберите Create Submenu:
При необходимости у созданных подменю можно создавать собственные подменю и т. д. Но особенно этим увлекаться не следует - слишком большая вложенность обычно не нужна.
Для создания заготовки обработчика для пункта меню достаточно на нем сделать двойной щелчок мышкой.
У меню может быть картинка (за это отвечает свойство Bitmap), оно может быть активным и неактивным (свойство Enabled). Правильнее картинки задавать не отдельно для каждого пункта меню, а с помощью компонента ImageList, представляющего из себя набор картинок. В этом случае в свойство Images для всего меню записываем имя компонента ImageList (по умолчанию это будет ImageList1), и затем для каждого пункта меню задаем свойство ImageIndex, которое и будет задавать номер картинки из ImageList. А еще удобнее делать все это через компонент ActionList.
Несколько пунктов меню могут объединяться в группу. Для такого объединения вы должны, во-первых, задать для всех этих пунктов меню одинаковое значение свойства GroupIndex. Во-вторых, необходимо установить у каждого из них свойство RadioItem в true. И, наконец, надо написать код, который будет устанавливать отметку рядом с выбранным пунктом меню( за это отвечает свойство Checked). Код может быть таким:
void __fastcall TForm1::Subitem1Click(TObject *Sender)
{
Subitem1->Checked=true;
<Действия при выборе первого пункта меню>
...
}
...
void __fastcall TForm1::Subitem2Click(TObject *Sender)
{
Subitem2->Checked=true;
<Действия при выборе второго пункта меню>
...
}
Обратите внимание, что если некоторому пункту меню установить свойство Checked в true, то у остальных пунктов из этой же группы оно автоматически установится в false. Теперь при выборе пункта меню из группы рядом с ним появится точка:
Компонент PopupMenu расположен на вкладке Standard Палитры компонентов:
Перенесите его на форму. Добавление пунктов для него происходит точно так же, как и для главного меню. Добавление обработчиков тоже делается точно так же.
Для того, чтобы приписать контекстное меню к какому-нибудь компоненту на форме, мы должны задать у последнего свойство PopupMenu:
После чего при щелчке правой кнопкой мыши на компоненте контекстное меню и появится.
При необходимости контекстное меню можно вызывать и другим способом. Например, нам надо, чтобы оно появлялось не всегда, а только при выполнении некоторого условия (скажем, если мы щелкнули на определенном месте формы). В этом случае нам надо для показа меню вызвать его метод Popup. У этого метода два параметра - X и Y того места, где контекстное меню должно появится. Вот пример использования этого метода:
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if ( X < 30)
{
TPoint point = ClientToScreen(Point(X, Y)); //Преобразуем кооринаты
PopupMenu1->Popup(point.x, point.y); //Показываем меню
}
}
В приведенном примере контекстное меню появится только если мы щелкнули на форме на расстоянии не больше чем 30 пикселов от левого края. Еще раз обратите внимание, что параметры X и Y у метода Popup контекстного меню - это координаты относительно всего экрана. В метод же FormMouseDown передаются координаты щелчка мыши относительно формы. Для преобразования одних координат в другие используем метод ClientToScreen.
Рассмотрим, как можно добавить на панель задач свой значок (т. е. значок для нашей программы расположится рядом с системными часами).
Сначала переносим на форму нашего приложения компонент TTrayIcon с вкладки Samples:
Этот компонент невизуальный, т. е. он не будет виден на этапе выполнения программы.
Далее разместите на форме еще два компонента - ImageList с вкладки Win32 и PopupMenu
с вкладки Standard. Наша форма будет вглядеть приблизительно так:
Теперь займемся установкой свойств. Сначала добавьте для компонента ImageList одно изображение. Для контекстного меню добавьте два пункта - с заголовками «Восстановить» и «Спрятать» соответственно (для этого надо сделать двойной щелчок на размещенном на нашей форме компоненте контекстного меню). Далее для формы и для компонента TrayIcon установите свойство PopupMenu в PopupMenu1 (именно такое имя получит наше контекстное меню по умолчанию). Кроме того для связывания компонента TrayIcon со списком изображений установите его свойство Icons в ImageList1. Для того, чтобы для нашего значка на панели задач появлялось контекстное меню, задайте его свойство PopupMenuOn в imRightClickUp (это означает, что оно будет появляться при щелчке правой кнопкой мыши). И, наконец, установите свойство Visible для компонента TrayIcon1 в true.
Теперь надо добавить обработчики для пунктов контекстного меню.
void __fastcall TForm1::N1Click(TObject *Sender)
{
// Восстановление формы.
Form1->Visible = true;
TrayIcon1->Restore();
}
void __fastcall TForm1::N2Click(TObject *Sender)
{
// Скрытие формы.
Form1->Visible = false;
}
Запускаем программу. После запуска мы увидите значок программы рядом с часами. При щелчке на нем правой кнопкой мыши появится контекстное меню:
Его пункты будут работать точно также, как и на форме.
Сплиттер позволяет разделить пространство формы на несколько частей. Размеры этих частей можно менять, двигая сплиттер.
Для начала создадим окно, разделенное по горизонтали на две части одним сплиттером. В каждой части разместим по компоненту Memo.
Разместите на форме компонент Memo. Он расположен на вкладке Stanard Палитры Компонентов:
Установите его свойство Align в alLeft. Memo прилипнет к левой части формы.
Теперь разместите на форме сплиттер. Он расположен на вкладке Additional Палитры Компонентов:
Для него свойство Align тоже установите в alLeft (если оно само не установилось в это значение).
Разместите на форме еще один экземпляр Memo. Для него свойство Align в alClient.
Можно запускать программу. Она будет выглядеть приблизительно так:
Аналогично можно делить форму сплиттером и на большее число частей. Например, если нам нужна форма такого вида - одна часть сверху и две - снизу (слева и справа):
то вы должны разместить на форме первый компонент Memo и установить его свойство Align в alTop, потом разместить один сплиттер и для него установить свойство Align тоже в alTop, затем расположить второй Memo, для которого свойство Align устанавливается в alLeft. Осталось разместить еще один сплиттер - для него свойство Align устанавливается как и для предыдущего Memo в alLeft, и, наконец, для последнего, третьего Memo свойство Align устанавливается в alClient.
И для первого, и для второго вариантов нашей программы мы можем менять размеры частей нашего окна, двигая сплиттер.
У сплиттера существует несколько полезных свойств. Например, толщина сплиттера. Она задается либо через свойство Width, либо через свойство Height - в зависимости от того, имеем мы дело с горизонтальным или вертикальным сплиттером.
Компонент Panel расположен на вкладке Standard и предназначен для компоновки объектов в окне:
Основное его свойство - это Align. Оно отвечает за то, как наша панель расположена в окне - прилеплена ли она, например, к верхнему или левому краю или же занимает всю клиентскую область окна. При этом при изменении размеров окна панель остается в определяемым этим свойством положении - т. е., например, если мы задали значение этого свойства в alRight, то при растягивании нашего окна по горизонтали панель все равно будет располагаться в правой части окна. Обратите внимание, что одно из значений этого свойства - это alClient. При задании этого значения панель будет занимать все оставшиеся место на форме. Например, если вы расположили на форме две панели и задали для них значения этого свойства в alLeft и alClient соотвественно, то первая панель будет располагаться в левой части формы (от верхнего края до нижнего), а вторая - занимать всю оставшуюся область. Причем при изменении размера окна такое расположение будет сохраняться.
Еще несколько полезных свойств панели отвечают за ее внешний вид. Например, свойства BevelInner и BevelOuter отвечают, как будет выглядеть граница нашей панели относительно своей внутренной и своей внешних частей. Например, если хотите, чтобы граница панели представляла из себя приподнятую границу, то эти два свойства надо установить в bvLowered и bvRaised соответственно. Если же мы хотим, чтобы панель выглядела как традиционная панель - безо всякой вдавленной внутренней части, то эти свойства устанавливаем в bvRaised и bvNone соответсвенно.
Еще одно свойство панели - это AutoSize. Оно если установить его в True, то панель будет стремится установить минимально возможный для себя размер. Так, например, если на панели ничего не расположено, то она примет нулевую ширину.
На панели могут располагаться другие компоненты. Все они будут храниться в коллекции Controls. Получить число элементов на панели можно через свойство ControlCount.
Вот пример кода, который делает все элементы на панели Panel1 невидимыми:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TControl *child;
int n = Panel1->ControlCount;
for(int i = 0; i < n; i++)
{
((TControl*)Panel1->Controls[i])->Visible = false ;
}
}
Если использовать только сплиттеры, то некоторые способы разбиения формы на части осуществить невозможно. Например, только сплиттерами невозможно добиться, чтобы у нас была одна область слева (по всей высоте формы) и 2 области друг над другом справа:
Но это можно сделать с помощью сплиттеров и панелей.
Например, вот так:
Размещаем на форме панель, устанавливаем ее свойство Align в alLeft. Затем щелкаем на свободном месте формы и затем размещаем в нем сплиттер. Его свойство Align также устанавливаем в alLeft. Опять щелкаем на свободном месте формы и размещаем в нем вторйю панель. Для нее устанавливаем свойство Align в alClient. Таким образом мы получили две панели (слева и справа), разделенные сплиттером.
Теперь на левой панели размещаем Memo1, его свойство Align устанавливаем в alClient. На правой же панели сначала размещаем верхний Memo (для него свойство Align устанавливаем в alTop), затем размещаем на этой же правой панели сплиттер (устанавливаем для него свойство Align в alTop) и, наконец, нижний Memo - для него свойство Align устанавливаем в alClient.
После запуска программы получаем желаемое разбиение нашей формы.
Компонент HotKey предназначен для назначения пользователем различных комбинация клавиш для выполнения той или иной команды (как правило, команды меню). Он расположен на вкладке Win32 Палитры компонентов:
Перенесите его на форму (оставьте его имя HotKey1 по умолчанию). Также добавьте на форму главное меню с подменю, в обработчике щелчка по подменю вставьте, например, вывод сообщения:
void __fastcall TForm1::MenuItem1Click(TObject *Sender)
{
ShowMessage("!!!");
}
Сейчас единственный способ выполнить действие для нашего пункта меню - это кликнуть на нем. Никаких комбинаций клавиш просто нет. А вот с помощью добавленного на форму компонента HotKey мы и предоставим пользователю такую возможность. Для этого добавьте еще на форму кнопку, в обработчике щелчка по ней напишите следующий код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MenuItem1->ShortCut = HotKey1->HotKey;
}
Тут мы просто присваиваем свойству ShortCut нашего пункта меню значенение свойства HotKey нашего элемента HotKey1. Потому что именно в свойство HotKey и запишется заданная пользователем на этапе работы программы некоторая комбинация клавиш.
Запускаем программу. Введем некоторую комбинацию клавиш в наш HotKey и нажмем на кнопку. Теперь при нажатии заданной пользователем комбинации клавиш и будет
выполнятся команда пункта меню:
Компонент StatusBar расположен на вкладке Win32 Палитры компонентов:
Разместите его на форме. Обычно на строке состояния располагаются несколько панелей. Наш пример не будет исключением из этого правила. Панели мы можем добавлять как динамически - по нажатию на кнопку, например, так и при разработке программы.
Для добавлении панели на этапе разработки программы выберите меню AddItem в
контекстном меню панели состояния в окне Object TreeView:
Другой способ добавления панелей к строке состояния - это нажатие на кнопку с многоточием для свойства Panels окна Object Inspector.
Для добавленной панели можно потом настраивать ее немногочисленные свойства в окне Object Inspector (например, такие, как текст (Text) или выравнивание (Alignment)).
Теперь посмотрим, как можно добавлять панели динамически. Добавьте на форму кнопку, в обработчике которой напишите следующий код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
StatusBar1->Panels->Add();// Добавляем панель
// Подсчитываем число панелей.
int count = StatusBar1->Panels->Count;
// Изменяем текст у последней панели.
StatusBar1->Panels->Items[count-1]->Text = "Panel " +IntToStr(count-1);
}
Результат будет приблизительно таким:
Иногда нет необходимости разбивать строку состояния на панели. В этом случае мы используем не коллекцию Panels, а свойство SimpleText. Вот так, например, можно вывести некоторый текст в строку состояния:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
StatusBar1->SimpleText = "Это текст";
}
В большом приложении у вас, как правило, имеется несколько форм. По умолчанию в начале работы программы запускается форма, созданная первой. Но часто требуется поменять форму, запускаемой первой. Вот как это делается:
Выбираем Project -> Options в главном меню C++ Builder IDE. В появившемся диалоговом окне Project Options for Project1.exe переходим на вкладку Forms, в которой в Combobox'е Main form выбираем нужную нам форму:
После этого именно выбранная нами форма и будет появляться первой при запуске нашей программы.
Для рисования на форме надо использовать свойство Canvas формы. Оно имеет тип TCanvas. У этого типа есть целый ряд методов, которые позволяют рисовать различные примитивы, выводить текст, показывать картинки из файла и др.
Вот пример использования:
// Запоминаем текущую кисть
TColor oldColor = Form1->Canvas->Brush->Color;
// Меняем текущую кисть
Form1->Canvas->Brush->Color = RGB(255, 0, 0);
// Вывод примитивов
Form1->Canvas->Ellipse(100, 100, 150, 150);
Form1->Canvas->MoveTo(200, 100);
Form1->Canvas->LineTo(200, 200);
Form1->Canvas->LineTo(300, 100);
Form1->Canvas->LineTo(200, 100);
Form1->Canvas->Rectangle(70, 100, 90, 180);
// Возврат старой кисти и вывод текста
Form1->Canvas->Brush->Color = oldColor;
Form1->Canvas->TextOutA(100, 160, "Picture");
// Вывод картинки из файла
Graphics::TBitmap * gr = new Graphics::TBitmap;
gr->LoadFromFile("C:\\1.bmp");
Form1->Canvas->Draw(100, 180, gr);
Этот код можно поместить, например, в обработчике нажатия на кнопке на некоторой форме.Результат выполнения приведенного кода будет приблизительно таким:
Компонент ActionList расположен на вкладке Standard Палитры компонентов:
Основное его назначение - это хранение в одном месте некоторых действий, которые должны выполняться тем или иным способом. Как правило, одно и тоже вы можете сделать разными способами - через пункт меню, нажатием на кнопку и тому подобное. При этом ваше действие может быть, скажем, временно недоступно - и в этом случае вы хотите, чтобы соответствующий пункт меню и соответствующая кнопка были недоступны. Так вот, если действие одно, а способов его выполнения много, то и надо использовать компонент ActionList. В этом случае обработчик пишется только в одном месте, и если вам, скажем, надо отключить возможность выполнения этого действия во всех местах или во всех местах изменить его название (например, со Start на Stop), то вам не придется изменять много мест в вашем коде - достаточно только внести изменения в соответствующее действие для ActionList'а.
Посмотрим на примере, как это делается. Разместите на форме компонент MainMenu, обычную кнопку и компонент ActionList. Свойство name оставьте для всех компонентов без изменений. Для меню создайте одно меню верхнего уровня с заголовком Actions и в нем одно подменю (для этого просто щелкните на компоненте MainMenu1 на нашей форме).
Теперь добавим для компонента ActionList1 действие. Для этого сделайте на нем двойной щелчок. Появится окно Editing Form1->ActionList1 специального редактора. Нажмите в нем на кнопку New Action. В правой части появится новое действие Action1:
Сделайте двойной щелчок на Action1 для перехода в окно кода. В полученной заготовке добавьте следующую строку:
void __fastcall TForm1::Action1Execute(TObject *Sender)
{
ShowMessage("Некоторое действие");
}
Таким образом нашим действием просто будет появление MessageBox'а.
Теперь припишем наше действие к подпункту меню и кнопке. Для этого надо просто задать для них свойство Action (т. е. выбрать из ниспадающего списка Action1 - оно там будет одно):
Это надо сделать как для кнопки, так и для пункта меню.
Можно запустить программу и проверить - при выборе нашего пункта меню и нажатии на кнопке должен появиться MessageBox с надписью "Некоторое действие".
Теперь посмотрим, как мы можем вносить одновременные изменения во все компоненты, связанные с нашим действием Action1. Для этого снова переходим в редактор для ActionList1 (для чего сделайте на расположенном на форме компонете ActionList1 двойной щелчок), выделяем наше действие Action1 и в Инспекторе объектов на вкладке Events делаем двойной щелчок на OnUpdate:
В появившуюся заготовку для кода внесите следующие строки:
void __fastcall TForm1::Action1Update(TObject *Sender)
{
if(b)
{
((TAction *)Sender)->Caption = "New caption";
((TAction *)Sender)->Enabled=false;
}
}
Что мы тут делаем? В зависимости от значения некоторой переменной b (которую мы еще добавим) мы меняем у нашего действия заголовок на "New caption" и делаем его отключенным.
Объявление переменной b добавьте в заголовочный файл нашей формы:
class TForm1 : public TForm
{
...
public:
bool b; // User declarations
...
Осталось еще где-то вызывать обновление нашего Action1. Например, это можно сделать при нажатии на вторую кнопку. Добавьте на форму вторую кнопку и в ее обработчик внесите следующий код:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
b=true;
ActionList1->Actions[0]->Update(); //Обновляем Action1
}
После запуска программы и нажатии на вторую кнопку у пункта меню и у первой кнопки одновременно поменяется заголовок и они станут недоступны:
Приложение редко состоит только из одной формы. Почти в любой программе есть дополнительные формы с разными настройками и параметрами. Для добавления в программу еще одной формы нажмите на кнопочку New Form:
Появится еще одна форма. Разместите на ней Edit и две обычные кнопки. Для первой кнопки задайте свойство Caption как "OK", для второй - "Cancel". Пользователь будет задавать в Edit некоторый параметр, который мы будем передавать в главное окно нашего приложения. Появляться же наша вторая форма будет по некоторому действию пользователя (выбору пункта меню, щелчку мыши и т. п.). Напишем теперь код, по которому наше второе окно будет появляться. Для этого, во-первых, добавьте строку
...
#include "Unit1.h"
#include "Unit2.h"
...
в файл Unit1.cpp реализации первой формы.
И, во-вторых, добавьте код для показа второй формы в модальном виде:
...
Form2->ShowModal();
...
Добавить его можно, например, в обработчике меню (или там, где вы хотите, чтобы ваше второе окно появилось).
Запускаем программу и проверяем. Второе окно появляется при выборе пункта меню. Правда, кнопки OK и Cancel не работают. Напишем для них соответствующий код. Добавьте для обработчиков нажатия на кнопки OK и Cancel такой код:
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Close(); //Закрываем форму
ModalResult = mrOk; //Результат закрытия - mrOk
}
...
void __fastcall TForm2::Button2Click(TObject *Sender)
{
Close(); //Закрываем форму
ModalResult = mrCancel; //Результат закрытия - mrCancel
}
Метод Close() закрывает окно, а в свойство ModalResult второй формы мы записываем значение, соответствующее нажатой пользователем кнопки. Оно будет результатом, возвращаемым функцией запуска формы. Осталось переделать код для показа второй формы. Измените его следующим образом:
...
if (Form2->ShowModal() == mrOk) //Если нажата кнопка OK
Form1->Caption=Form2->Edit1->Text; //то меняем заголовок у формы
...
Как вы видите, мы тут анализируем, что за кнопку пользователь нажал. Если эта была OK, то меняем заголовок у формы на заданное пользователем значение, если Cancel, то ничего не делаем.
В программах для Windows на C++ Builder, как правило, все API-функции можно использовать без особых проблем и без дополнительных объявлений и include'ов. Вот пример, как можно с помощью API-функций сдвинуть кнопку Пуск на Панели задач:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HWND hWnd = FindWindow("Shell_TrayWnd", NULL);
HWND hWndBt = FindWindowEx(hWnd, NULL, "Button", NULL);
MoveWindow(hWndBt, 30, 2, 98, 32, TRUE);
}
Разумеется, этот код надо разместить в обработчике нажатия на кнопку на форме. После щелчка на кнопке нашей программы кнопка "Пуск" сдвинется вправо:
Если же вы разместите этот код в консольном приложении, то вам необходимо добавить файл windows.h:
#include <windows.h>
int main(int argc, char* argv[])
{
HWND hWnd = FindWindow("Shell_TrayWnd", NULL);
HWND hWndBt = FindWindowEx(hWnd, NULL, "Button", NULL);
MoveWindow(hWndBt, 30, 2, 98, 32, TRUE);
return 0;
}
Как правило, этого include'а достаточно для использования любой API-функции в консольном приложении.
Некоторые API-функции требуют в Windows-приложениях дополнительных include'ов. Например, функция PlaySound. Она без проблем будет работать в консольном приложении (если файл windows.h подключен, разумеется), в Windows же приложении нужно добавить строчку
...
#include <Mmsystem.h>
...
после чего в вашей программе вы сможете проигрывать с помощью этой функции звуки:
...
PlaySound("music.wav", NULL, SND_FILENAME);
...
Приведенный фрагмент проиграет файл music.wav, который вы должы разместить в папке вашего проекта.
Рассмотрим две функции вывода на экран окна сообщений: ShowMessage и MessageDlg. Первая из них позволяет вывести на экран простое окно сообщения, вторая - окно с дополнительными параметрами (несколько кнопок, иконка и др.)
Обе эти функции выводят модальное окно.
Начнем с ShowMessage. Вот сразу пример:
ShowMessage("Ошибка!");
Этот пример выведет сообщение "Ошибка!". Никаких дополнительных параметров у функции ShowMessage нет - только текст вообщения.
А вот функция MessageDlg позволяет задавать для выводимого окна сообщения ряд дополнительных параметров. Вот пример использования этой функции:
MessageDlg("Внимание!", mtInformation, TMsgDlgButtons() << mbNo << mbYes, 0);
Первый параметр у этой функции - это текст сообщения, второй (типа TMsgDlgType) - значок сообщения. Этот параметр может принимать следующие значения:
Значение |
Описание |
mtWarning |
Предупреждение |
mtError |
Ошибка |
mtInformation |
Информация |
mtConfirmation |
Подтверждение |
mtCustom |
Картинка отсутствует, в заголовке окна - название файла программы. |
Третий параметр функции MessageDlg - это кнопки, показываемые в окне сообщения. Для задания кнопок мы используем следующую конструкцию:
TMsgDlgButtons() << mbNo << mbYes
В этом параметре могут использоваться следующие константы:
mbOK, mbCancel, mbYes, mbNo, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp.
Четвертый параметр - это идентификатор справки для нашего окна сообщения.
Функция MessageDlg возвращает значение, которое соответствует нажатой кнопке. Вот пример:
if(mrOk == MessageDlg("Внимание!", mtInformation,
TMsgDlgButtons() <<mbOK<<mbCancel , 0))
{
//Операторы для случая OK.
}
else
{
//Операторы для случая Cancel.
}
Константы для выяснения того, на какой кнопке пользователь нажал, соответствуют константам для кнопок, только вместо префикса mb имеют префикс mr (например, вместо mbCancel - mrCancel и так далее).
В библиотеке VCL есть два компонента, предназначенных для работы с сетью на низком уровне - т. е. на уровне протоколов TCP/IP. Это компоненты ClientSocket и ClientSocket. Оба они расположены на вкладке Internet.
На этом уроке мы с вами создадим клиента. Создайте новое приложение, на форме разместите 2 кнопки, Edit и компонент ClientSocket с вкладки Internet:
Задайте для первой кнопки свойство Caption как "Соединиться", для второй - "Отправить", свойство Text для Edit1 установите в "" (пустую строку).
Программа будет работать так: сначала мы подсоединяемся к серверу, нажав на кнопку "Cоединитmся", затем вводим некоторые данные в Edit1 и отправляем их серверу, нажав на кнопку "Отправить".
Наша форма после размещения всех компонентов должна выглядеть приблизительно так:
Теперь займемся настройкой сокета. Устанавливаем для него Address в 127.0.0.1 (так как тестирование мы будем делать на локальном компьютере), порт в 2000 (тут можно поставить и любое другое число - важно только, что сервер, который мы сделаем на следующем уроке, будет слушать именно порт с этим номером).
Теперь займемся кодом для кнопок. Для кнопки с заголовком "Соединиться" пишем код соединения к серверу:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ClientSocket1->Active = true;
}
Тут мы просто активизируем сокет, но для него уже установлены свойства Port и Address, так что мы именно по этому адресу и именно к этому порту и будем подсоединятся.
Теперь код для второй кнопки:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ClientSocket1->Socket->SendText(Edit1->Text);
}
Тут наш сокет просто посылает данные из edit'а на сервер.
С написанием клиента все!
Приступаем к написанию сервера. Для этого создайте новый проект, на форме разместрите Edit (в нем будут появляется отправленные с клиента данные), кнопку (по ней сервер начнет слушать сеть) и компонент ServerSocket с вкладки Internet:
Начинаем менять свойства. Для кнопки свойство Caption измените на "Слушать", свойство Text для Edit установите в "" (пустую строку), свойство Port для серверного сокета установите в 2000 (как и у клиентского сокета).
После всего наша форма будет выглядеть приблизительно так:
Теперь добавим код для кнопки :
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ServerSocket1->Active=true;
}
Теперь сервер начинает слушать сеть по 2000 порту, ожидая, когда к нему подсоединится клиент.
Осталось добавить коды для сокета - а именно код, выполняющийся при установке соединения и код, выполняющийся при получении данных от клиента. Для этого переходим в Инспекторе объектов на вкладку Events при выбранном сокете ServerSocket1 и создаем двойным щелчком заготовки кода для OnClientConnect (этот код будет выполняться при подсоединении клиента) и OnClientRead (этот код будет выполняться при получении данных от клиента).
В заготовках напишите следующий код:
void __fastcall TForm1::ServerSocket1ClientConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
Form1->Caption="Клиент подсоединился";
}
Тут мы просто показываем в заголовке формы, что клиент подсоединится.
void __fastcall TForm1::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
Edit1->Text=Socket->ReceiveText();
}
Полученные от клиента данные будут показаны в Edit1.
Теперь испытываем наше творение. Запускаем сервер, нажимаем в нем на кнопку "Слушать". Далее запускаем клиента, нажимаем в нем на кнопку "Подсоединится". В сервере заголовок формы поменяется на "Клиент подсоединился". Теперь в клиенте печатаем что-нибудь в Edit'е и нажимаем на кнопку "Отправить". То, что мы отправили, покажется в Edit'е на сервере:
Это может оказаться полезным для разных задач - например, вы хотите одновременно изменить положение всех элементов формы или просто определить, есть ли среди элементов элемент с определенными свойствами.
Для нашей задачи мы будем использовать свойство Controls формы. Это свойство представляет из себя набор всех дочерних элементов формы - кнопок, Edit'ов, Label'ов и т. п. Каждый элемент этого набора имеет тип TControl (родительский тип для всех элементов).
Вот пример кода, который сдвигает все элементы на форме к левому краю формы:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TControl *child; //Переменная для элемента формы
for(int i = 0; i < Form1->ControlCount; i++)
{
child = Form1->Controls[i]; //Берем очередной элемент
child->Left=10; //Сдвигаем его влево на 10 пиксел
}
}
Как вы видите, мы получаем i-элемент на форме просто указав его индекс.
Нумерация при этом, как и следовало ожидать, идет с нуля. Для получения же общего количества элементов мы используем свойство ControlCount:
... i < Form1->ControlCount; ...
У формы могут быть собственные методы. Для их быстрого добавления сделайте следующие действия:
В дереве классов (оно распологается слева от окна кода) выберите нужный класс формы и щелкните на нем правой кнопкой мыши для показа контекстного меню. В контекстном
меню выберите New Method:
В появившемся диалоговом окне Add Method задайте имя метода, возможные параметры, тип возвращаемого значения, модификаторы доступа (private, public и т. п.) и другие характеристики:
Нажимите на OK для закрытия окна или на Apply для добавления еще одного метода. Созданная нами заготовка для метода появится в дереве классов:
Все. Теперь ослось только написать код метода в созданной заготовке.
Поля - это внутрение переменные класса. Для добавления поля надо щелкнуть правой кнопкой мыши на имени формы в дереве классов (слева от окна кода) и в появившемся контекстном меню выбрать New Field:
В появивщемся окне Add Field задаем имя поля, тип и область видимости:
При необходимости, не закрывая это окно, можно добавить несколько переменных (полей) как в класс одной формы, так и в несколько. Для этого надо нажать на кнопку Apply. При этом в классе сразу создастся переменная заданного типа с заданным именем и в диалоговом окне можно будет задавать следующую переменную.
Добавленная нами переменная появится в дереве классов:
Для добавления свойства щелкаем на классе правой кнопкой мыши и появившемся контекстном меню выбираем New Property:
Появится окно Add Property. В этом окне можно задать свойство разным способом. При любом способе мы задаем имя свойства и его тип.
Способ первый - можно создать свойство, привязанное к определенному полю. Например, к полю num, заданному на прошлом уроке. Для этого мы должны в нашем диалоговом окне выбрать название поля num в Combobox'ах Reads и Writes ():
После нажатия на OK наше свойство появится на в дереве классов:
Второй способ - не использовать для нашего свойства готовое поле, а позволить Builder'у автоматически создать новое. Для этого мы после задания имени и типа нового свойства должны поставить галочку create field:
После нажатия на OK новое свойство и соответствующее ему поле появятся в классе
нашей формы:
__published:
int FData; // User declarations
public:
...
__property int Data = { read=FData, write=FData };