- •Лекція №5
- •1. Перелік компонентів введення і відображення текстової інформації
- •2. Відображення тексту із використанням компонентів Label, StaticText, Panel
- •3. Поля (вікна) редагування Edit, LabeledEdit і MaskEdit
- •4. Багаторядкові вікна редагування Memo і RichEdit
- •5. Компоненти вибору із списків — ListBox, CheckListBox, ValueListEditor, ComboBox, ComboBoxEx
- •6. Таблиця рядків — компонент StringGrid
5. Компоненти вибору із списків — ListBox, CheckListBox, ValueListEditor, ComboBox, ComboBoxEx
Компоненти, що розглянуті в даному розділі - забезпечують вибір із списку.
Використання цих компонентів дозволяє забезпечити безпомилкове введення інформації користувачем в тих випадках, коли він повинен вибрати відповідь з кінцевої множини значень.
Компоненти ListBox і CheckListBox відображають списки рядків і дозволяють користувачу вибрати в них потрібний рядок. Основна властивість обох компонентів, що містить список рядків, — Items, яка має тип TStrings. Заповнити цей список під час проектування можна, натиснувши кнопку з багатокрапкою біля цієї властивості у вікні Інспектора Об'єктів. Під час виконання програми можна користуватися властивостями і методами класу TStrings - Clear, Add та іншими. Цей же клас дозволяє поставити у відповідність кожному рядку деякий об’єкт. Тоді вибір користувачем рядка в списку можна програмно співвідносити з цим об'єктом.
У компоненті ListBox є властивість MultiSelect, що дозволяє користувачу множинний вибір в списку. Якщо MultiSelect = false (значення за умовчанням), то користувач може вибрати тільки один елемент списку. В цьому випадку можна дізнатися індекс вибраного рядка з властивості ItemІndex, доступної тільки під час виконання. Якщо жоден рядок не вибраний, то ItemІndex = -1.
Наприклад, наступний код перевіряє вибір користувача. Якщо вибір не зроблений, з'являється повідомлення «Ви не зробили свій вибір». Якщо один з елементів списку вибраний, то з'являється повідомлення вигляду «Ваш вибір..: ...», де замість першої багатокрапки відображається номер вибраного рядка, а замість другої багатокрапки — текст вибраного рядка:
if (ListBoxl->ItemIndex < 0)
ShowMessage("Ви не зробили свій вибір");
Else
ShowMessage("Ваш вибір " +
IntToStr(ListBoxl->ItemIndex + 1) + ": " +
ListBoxl->Items->Strings[ListBoxl->ItemIndex]);
Початкове значення ItemІndex неможливо задати під час проектування. За умовчанням ItemІndex = -1, Це означає, що жоден елемент списку не вибраний. Якщо ви хочете задати цій властивості якесь інше значення, тобто встановити вибір за умовчанням, який буде показаний у момент початку роботи програми, то зробити це можна, наприклад, в обробнику події OnCreate форми, ввівши в нього оператор:
ListBoxl->ItemIndex = 0;
Якщо допускається множинний вибір (MultiSelect = true), то значення ItemІndex відповідає тому елементу списку, який знаходиться у фокусі. При множинному виборі можна перевірити, чи вибраний даний елемент, по властивості Selected[int Index] типу bool. Наприклад, наступний код відображає повідомлення вигляду "Вибраний рядок .... ..." (схожі на попередній приклад) про всі вибрані рядки:
for (int i = 0; i < ListBox1->Items->Count; i++)
if (ListBox1->Selected[i])
ShowMessage("Вибраний рядок " + IntToStr(i+1) + ": " +
ListBoxl->Items->Strinos [i]);
На спосіб множинного вибору при MultiSelect = true впливає ще властивість ExtendedSelect. Якщо ExtendedSelect = true, то користувач може виділити інтервал елементів, виділивши один з них, потім натиснувши клавішу Shift і перевівши курсор до іншого елементу. Виділити не прилеглі один до одного елементи користувач може, якщо утримуватиме під час вибору натиснутої клавішу Ctrl, Якщо ExtendedSelect = false, то клавіші Shift і Ctrl при виборі не працюють.
Властивість Columns визначає число стовпців, в яких відображатиметься список, якщо він не поміщається цілком у вікні компоненту ListBox.
Властивість Sorted дозволяє упорядкувати список за абеткою. При Sorted = true нові рядки в список додаються не в кінець, а за абеткою.
Властивість AutoComplete, якщо встановити його в true, дозволяє користувачу швидко знаходити рядок списку, натискаючи клавішу, відповідну її першому символу.
Властивість Style, встановлена в lbStandard (значення за умовчанням) відповідає списку рядків. Інші значення Style дозволяють відображати в списку не тільки текст, але і зображення, а в C++Builder 6 введена можливість створювати віртуальні списки.
Значення lbOwnerDrawFixed і lbOwnerDrawVariable використовуються для занесення в список зображень. При цьому lbOwnerDrawFixed означає, що висота всіх елементів списку однакова, а значення lbOwnerDrawVariable означає, що висота елементів може бути різною. Значення lb Virtual і lbVirtualOwner-Draw відповідають віртуальним спискам відповідно з рядками текстів і зображень.
При значенні Style, рівному lbOwnerDrawFixed або lbOwnerDrawVariable, в момент, коли повинен малюватися якийсь рядок списку, наступає подія OnDrawItem. Заголовок обробника цієї події має вигляд:
void __fastcall TForml::ListBoxlDrawItem(
TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
Параметр Control є покажчиком на список, в якому відбувається подія. Параметр Index указує індекс елементу, який повинен перемальовуватися. Параметр Rect типу TRect вказує область канви списку, відповідну за зображення елемента списку. Параметр TOwnerDrawState є множиною, елементами якої можуть бути значення odSelected — рядок виділений, odFocused рядок знаходиться у фокусі і ряд інших.
У обробнику події OnDrawItem треба методами роботи на канві намалювати зображення елементу.
При значенні Style рівному lbOwnerDrawFixed перед промальовуванням наступає тільки подія OnDrawItem. При Style = lbOwnerDrawVariable перед цією подією наступає інша — OnMeasureІtem, в якому треба вказати висоту елементу. Заголовок обробника цієї події має вигляд:
void __fastcall TForm1::ListBox1MeasureІtem(
TWinControl *Control, int Index, int SHeight)
Параметри Control і Index мають той же смисл, що і в обробнику OnDrawItem, а значення параметра Height треба задати рівним висоті даного елементу списку.
Ми детально розглянули список ListBox. Є ще один компонент, дуже схожий на ListBox — це список з індикаторами CheckListBox, Виглядає він так само, як ListBox, але біля кожного рядка є індикатор, який користувач може перемикати. Індикатори можна перемикати і програмно, якщо список використовується для виведення даних і необхідно в ньому відзначити якусь характеристику кожного об'єкту, наприклад, наявність товару даного найменування на складі.
Властивості компоненту CheckListBox, пов'язані з індикаторами, будуть розглянуті пізніше. Решта властивостей, що характеризують компонент CheckListBox як список, аналогічні ListBox, за винятком властивостей, що визначають множинний вибір. Ці властивості компоненту CheckListBox не потрібні, оскільки в ньому множинний вибір можна здійснювати установкою індикаторів.
У C++Builder 6 в CheckListBox з'явилися нові властивості, що дозволяють розбити список на декілька розділів за допомогою заголовків. Властивість Header є індексованим масивом булевих значень, що визначають, чи є відповідний рядок заголовком (значення true), або це звичайний рядок з індикатором (значення false). Властивість Header — тільки часу виконання і повинна заповнюватися програмно (за умовчанням всі значення рівні false). Наприклад, оператори
CheckListBox1->Header[1] = true;
CheckListBox1->Header[9] = true;'
задають як заголовки другий і десятий рядки.
Заголовки відображаються в рядках з кольором фону, який визначається властивістю HeaderBackgroundColor, і кольором напису, властивістю HeaderColor, що задається.
Розглянемо тепер компонент ValueListEditor. Це вікно редагування списку рядків вигляду «ім'я - значення». Вікно має дві колонки із заголовками «Key» для імен і «Value» для значень. Заголовки можна змінити під час проектування або програмно, використовуючи властивість TitleCaptions типу TStrings. Перший рядок цієї властивості відповідає першій колонці (іменам), друга — другій колонці (значення).
Властивість Strings типу TStrings містить список всіх рядків. Під час проектування він може бути заповнений через редактор рядків, що викликається з Інспектора Об'єктів. Під час виконання користувач може заповнювати його, якщо в компоненті дозволено редагування. Можна також програмно привласнити властивості Strings зміст деякого іншого списку типу TStrings. Всі рядки привласненого списку повинні мати вигляд «ім'я = значення». Тоді вміст списку відобразиться в колонках компоненту. Методи класу TStrings дозволяють маніпулювати списком, додавати рядки, видаляти і т.п.
Властивість Keys є індексованим списком імен. Індекси починаються з 1. Властивість AnsiString Values[const AnsiString Key] дозволяє задати або прочитати значення з рядка з ім'ям Key. Якщо властивість використовується для завдання значення, а імені Key в списку немає, то в список додається новий рядок з вказаним ім'ям і значенням. Якщо властивість використовується для читання, а імені Key в списку немає, то повертається порожній рядок.
Доступ до імен і значень дають також властивості Strings ->Names і Strings—>Values (як в звичайних списках типу TStrings).
Ще один спосіб доступу до елементів рядків дає властивість AnsiString Cells[int ACol][int ARow]. У цій властивості ACol = 0 відповідає колонці імен, а ACol = 1 - колонці значень. ARow = 0 відповідає рядку заголовків, а ARow > 0 — рядкам списку.
Властивість тільки для читання RowCount показує число рядків, включаючи рядок заголовка.
Властивість KeyOptions дозволяє визначити операції, доступні користувачу при редагуванні колонки імен. Ця властивість є множиною, яка порожня або містить елементи keyEdit, keyAdd, keyDelete, keyUnique. Елемент keyEdit дозволяє користувачу редагувати імена в першій колонці. Елемент keyAdd дозволяє користувачу додавати в список нові рядки, використовуючи клавішу Insert або переміщаючи курсор клавішею із стрілкою нижче за позицію останнього рядка. Елемент keyAdd можна включати тільки разом з keyEdit. Елемент keyDelete дозволяє користувачу видаляти виділений рядок клавішею Delete. Елемент keyUnique не дозволяє користувачу додати новий рядок з ім'ям, вже наявним в списку. Така спроба приводить до генерації виключення.
Властивість тільки часу виконання ItemProps дозволяє управляти способом редагування користувачем значення кожного з елементів списку. Елемент задається або його ім'ям, або індексом рядка (починаються з 0). Масив ItemProps містить об'єкти класу TItemProp, що описують доступ до відповідного елементу. Властивості цього класу задають способи редагування значень:
EditMask - масковане введення;
EditStyle - Стиль редагування:
esSimple - звичайне вікно редагування;
esEllipsis - Кнопка з багатокрапкою, при натисненні
на яку виникає подія OnEditButtonClick.
У обробнику цієї події можна передбачити виклик вікна спеціалізованого редактора властивостей.
esPickList - випадаючий список, рядки якого
задаються властивістю PickList
або в обробнику події OnGetPickList
(можна поєднувати ці дві можливості,
задаючи список в PickList і
модифікуючи його в обробнику OnGetPickList).
KeyDesc - ім'я, що з'являється в рядку даного елементу
списку в колонці «Key»;
MaxLength - максимальне число символів, що вводяться;
PickList - список типу TStrings, що з'являється у випадаючому
списку при значенні EditStyle = esPickList;
ReadOnly - тільки для читання, редагування заборонене.
Наприклад, поєднання ReadOnly = true і стилю
EditStyle = esPickList або esEllipsis, не дасть користувачу
задати значення інакше, як вибравши його із списку або ввівши
за допомогою редактора властивості.
Пояснимо деякі можливості властивості ItemProps. Оператор
ValueListEditor1->ItemProps["Телефон"]->EditMask="!000-00-00;0;";
задає маску введення семизначного номера телефону.
Стиль EditStyle = esPickList призводить до того, що при спробі користувача редагувати значення він бачить кнопку випадного списку, з якого він може вибрати відповідне значення. Якщо при цьому задати ReadOnly = true, то користувач не зможе змінити значення інакше, ніж вибором із списку. Як приклад приведемо оператори, що забезпечують вибір:
Valedit::TІtemProp *ItemProp =
ValueListEditor1->ItemProps["Відділ"];
ItemProp->EditStyle = esPickList;
ItemProp->PickList~>Add("Управління");
ItemProp->PickList->Add("Цex1");
ItemProp->PickList->Add{"Цex2");
ItemProp->ReadOnly = true;
Стиль EditStyle — esEllipsis призводить до того, що при спробі користувача редагувати значення він бачить кнопку з багатокрапкою. При натисненні на неї виникає подія OnEditButtonClick. У її обробнику можна, наприклад, викликати якесь діалогове вікно, в якому користувач повинен відповісти на якісь питання. В результаті буде вироблене значення, яке занесеться в рядок списку. Наприклад:
ValueListEditor1->Values["Посада"] = "Двірник";
Якщо до того ж задати для цього рядка ReadOnly = true, то користувач не зможе задати значення інакше, ніж в результаті роботи цього діалогу.
Властивість DisplayOptions є множиною, яка може містити елементи doColumnTitles — рядок заголовка фіксований (не прокручується), doKeyColFixed — ширина колони імен незмінна, doAutoColResize — при зміні ширини компоненту ширина колонок автоматично змінюється.
Властивість Options містить безліч опцій, що управляють відображенням ліній таблиці, можливість для користувача змінювати розміри колонок і т.п.
Розглянемо тепер компоненти випадаючих списків: ComboBox і ComboВохЕх.
Стиль зображення компоненту ComboBox визначається його властивістю Style,
яке може приймати наступні основні значення:
csDropDown - випадаючий список з рядками однакової висоти і з вікном редагування, що дозволяє користувачу вводити або редагувати текст.
csSimple - розгорнений список з рядками однакової висоти і з вікном редагування, що дозволяє користувачу вводити або редагувати текст. При такому стилі треба робити під час проектування або програмно висоту списку такою, щоб в ньому могло відобразитися необхідне число рядків.
csDropDownList - випадаючий список з рядками однакової висоти, і що не містить вікна редагування.
csOwnerDrawFixed - випадаючий список з рядками однакової висоти, в яких можуть відображатися зображення і текст.
csOwnerDraw Variable - випадаючий список з рядками різної висоти, в яких можуть відображатися зображення і текст.
При стилях csOwnerDrawFixed і csOwnerDrawVariable зображення малюються на канві в обробнику події OnDrawItem так само, як це розповідалося раніше для ListBox. При стилі csOwnerDrawVariable перед малюванням виникає подія OnMeasureІtem, в обробнику якого треба задати висоту елементу.
Вибір користувача або введений їм текст можна визначити по значенню властивості Text. Якщо ж треба визначити індекс вибраного користувачем елементу списку, то можна скористатися ListBox властивістю ItemІndex. Все сказане вище про ItemІndex і про завдання його значення за умовчанням справедливо і для компоненту ComboBox. Причому для ComboBox завдання початкового значення ItemІndex ще актуальніше, ніж для ListBox, Якщо початкове значення не задане, то у момент запуску програми користувач не побачить у вікні компоненту одне з можливих значень списку і, найімовірніше, не дуже зрозуміє, що з цим вікном треба робити.
До C++Builder 6 властивість ItemІndex у випаючих списках так само, як в списках, розглянутих раніше, була властивістю тільки часу виконання. Проте в C++Builder 6 ця властивість стала доступною і під час проектування. Отже значення ItemІndex можна тепер задавати не тільки програмно.
Якщо у вікні проводилося редагування даних, то ItemІndex = -1, За цією ознакою можна визначити, що редагування проводилося.
Властивість MaxLength визначає максимальне число символів, які користувач може ввести у вікно редагування. Якщо MaxLength = 0, те число символів, що вводяться, не обмежене.
Властивість DropDownCount указує число рядків, що з'являються у випадному списку без виникнення смуги прокрутки.
Як і в компоненті ListBox, властивість Sorted дозволяє упорядкувати список за абеткою. При Sorted = true нові рядки в список додаються не в кінець, а за абеткою.
На закінчення зупинимося на компоненті ComboBoxEx. Він багато в чому подібний ComboBox. Відмінність, перш за все, полягає в тому, що в ComboBoxEx легше, ніж в ComboBox, вводити зображення в елементи списку. З іншого боку, деякі можливості ComboBox, наприклад, можливість сортування, ComboBoxEx в не підтримуються. Неможливо також в цьому списку замовлене малювання на канві.
Зображення, що відображаються в елементах, повинні міститися в компоненті ImageList. Посилання на цей компонент задається у властивості Images. Введення елементів списку під час проектування здійснюється редактором колекцій, що викликається клацанням на кнопці з багатокрапкою у вікні Інспектора Об'єктів біля властивості ItemsEx. Кнопка AddNew (ліва) дозволяє ввести новий елемент. Якщо ви ввели елемент і виділили його, то у вікні Інспектора Об'єктів побачите його властивості. Основні з них: Caption — текстовий рядок, ImageІndex — індекс відповідної піктограми в списку ImageList, Indent — відступ від лівого поля елементу списку. Додавання малюнків в список зображень ImageList здійснюється викликом із контекстного меню команди ImageListEditor.
Властивість Style визначає стиль елементу і може бути рівним csExDropDown, csExSimple або csExDropDownList. Смисл цих значень подібний розглянутому вище для компоненту ComboBox.