Программируем смартфоны Symbian Series 60. Стандартные органы управления

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

Простой список


Элемент простого списка может содержать номер, иконку и одну или две строки текста. В S60 есть следующие простые списки:

CAknSingleStyleListBox — каждый пункт списка содержит только строку текста. Пункт списка должен задаваться в следующем формате:
"\t<текст>\t\t".

CAknSingleNumberStyleListBox — пункт содержит номер и строку текста. Формат строки: "<номер>\t<текст>\t\t".

CAknSingleHeadingStyleListBox — пункт содержит мелкий текст слева и строку текста нормального размера справа. Формат строки: "<текст слева>\t<текст справа>\t\t".

CAknSingleGraphicStyleListBox — пункт содержит маленькую иконку и текст. Формат строки: "<номер иконки>\t<текст>\t\t".

CAknSingleGraphicHeadingStyleListBox — пункт содержит иконку, мелкий текст слева и строку текста нормального размера справа. Формат строки: "<номер иконки>\t <текст слева>\t<текст справа>\t".

CAknSingleLargeStyleListBox — пункт содержит крупную иконку и текст. Формат строки: "<номер иконки>\t<текст>\t\t".

CAknDoubleStyle2ListBox — пункт содержит только строку текста, которая отображается в две строчки. Формат строки: "\t<текст>\t\t".

CAknDoubleStyleListBox — пункт содержит две строки текста, верхняя строка отображается нормальным шрифтом, нижняя — мелким. Формат строки: "\t<верхняя
строка>\t<нижняя строка>\t".

CAknDoubleNumberStyleListBox — пункт содержит номер и две строки текста (верхняя — нормальным шрифтом, нижняя — мелким). Формат строки: "<номер>\t<верхняя строка>\t<нижняя строка>\t".

CAknDoubleGraphicStyleListBox –– пункт содержит мелкую иконку и две строки текста (верхняя — нормальным шрифтом, нижняя — мелким). Формат строки: "<номер иконки>\t<верхняя строка>\t<нижняя строка>\t".

CAknDoubleLargeStyleListBox — пункт содержит крупную иконку и две строки текста (верхняя — нормальным шрифтом, нижняя — мелким). Формат строки: "<номер иконки>\t<верхняя строка>\t<нижняя строка>\t".

CAknFormDoubleGraphicStyleListBox — пункт содержит две строки текста: верхняя строка отображается мелким шрифтом, нижняя — крупным. Формат строки: "\t<верхняя строка>\t<нижняя строка>\t".

CAknSettingStyleListBox — пункт содержит две строки текста (верхняя — нормальным шрифтом, нижняя отображается в темном прямоугольнике мелким светлым шрифтом). Формат строки: "\t<верхняя строка>\t\t <нижняя строка> ".

CAknSettingNumberStyleListBox — похож на предыдущий, но пункт дополнительно имеет номер. Формат строки: "<номер >\t<верхняя строка>\t\t <нижняя строка> ".

Как видите, списков довольно много, но работа со всеми одинакова. Давайте разберемся на примере списка, содержащего иконку и текст (класс CAknSingleGraphicStyleListBox).

Есть два способа создания центральной панели в виде списка: создание списка во время выполнения программы и загрузка из ресурсов
приложения.

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

Создание главной панели в виде списка обычно выполняется в конструкторе ConstructL() класса, порожденного от CAknAppUi. Для создания списка во время выполнения программы необходимо сделать следующее:

1. Создать экземпляр класса списка:
iList = new (ELeave) CAknSingleGraphicStyleListBox;
iList->SetMopParent( this );
iList->ConstructL(NULL, EAknListBoxSelectionList);
iList->SetRect( ClientRect() );

Переменная iList обычно объявляется как:
CEikColumnListBox *iList;

Вторым параметром конструктора ConstructL идет константа, определяющая тип списка. Возможны следующие варианты:
EAknListBoxSelectionList — в списке всегда выбран только один пункт, это тип по умолчанию;
EAknListBoxMultiselectionList — в списке может быть выбрано сразу несколько пунктов. Выбор пункта выполняется нажатием на центр
пятипозиционной клавиши или джойстика (в зависимости от модели). Если используется список без иконок, то справа от помеченного пункта будет отображаться иконка с номером 0 (если вы не определите иконку, то программа аварийно закроется). В списках с иконками у помеченного пункта иконка будет меняться на иконку с номером 0;
EAknListBoxMarkableList — теоретически этот список представляет собой список чекбоксов, однако мне ни разу не удалось заставить его работать так, как надо, да и, судя по вопросам на различных форумах, не мне одному;
EAknListBoxViewerFlags — в списке нет выбранных пунктов, используется только для просмотра.

2. Если необходимо, создаем полосу прокрутки (Scrollbar) (в S60.1 и S60.2 это две стрелочки в управляющей панели, а в S60.3 — полоска с ползунком справа от окна):
iList->CreateScrollBarFrameL(ETrue);
iList->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);

У функции SetScrollBarVisibilityL() два аргумента: первый отвечает за горизонтальную полосу прокрутки, второй — за вертикальную. Возможны варианты:
EOn — всегда видна;
EOff — всегда не видна;
EAuto — видна, если необходимо.

3. Создаем массив пунктов:
CDesCArray *itemList = new (ELeave) CDesCArrayFlat(3);
CleanupStack::PushL(itemList);
itemList->AppendL(_L("0\tItem 1\t\t"));
itemList->AppendL(_L("1\tItem 2\t\t"));
itemList->AppendL(_L("2\tItem 3\t\t"));

4. Загружаем массив пунктов в список:
iList->Model()->SetItemTextArray(itemList);
iList->Model()->SetOwnershipType(ELbmOwnsItemArray);
CleanupStack::Pop(itemList);

Функция SetOwnershipType() определяет, кто является владельцем массива пунктов. Аргумент ELbmOwnsItemArray обозначает, что владельцем является список (в этом случае вам не надо заботиться об удалении массива в конце работы программы — это сделает владелец, т.е. список). Если же вы не хотите, чтобы список был владельцем массива, задайте аргумент ELbmDoesNotOwnItemArray.

5. Создаем массив иконок (если вы используете список с иконками) и добавляем его в список:
CArrayPtr<CGulIcon>* iconList = new (ELeave) CAknIconArray(3);
CleanupStack::PushL(iconList);
iconList->AppendL( iEikonEnv->CreateIconL(KIconFile, EMbmExamplelistIcon1, EMbmExamplelistIcon1_mask) );
iconList->AppendL( iEikonEnv->CreateIconL(KIconFile, EMbmExamplelistIcon1, EMbmExamplelistIcon1_mask) );
iconList->AppendL( iEikonEnv->CreateIconL(KIconFile, EMbmExamplelistIcon1, EMbmExamplelistIcon1_mask) );
iList->ItemDrawer()->ColumnData()->SetIconArray( iconList );
CleanupStack::Pop();

Здесь KIconFile — это имя mbm-файла с изображениями иконок и масок к ним (о mbm-файлах было рассказано в предыдущей статье). Прозрачность в маске задается белым цветом.

6. Обновляем список:
iList->HandleItemAdditionL();

Пока вы не вызовете функцию HandleItemAdditionL(), все добавленные вами в список пункты отображаться не будут.

7. Активируем список и устанавливаем список в качестве центральной панели:
iList->ActivateL();
AddToStackL(iList);
Все, создание списка закончено (результат см. на рисунке).

Для этого примера необходимы следующие заголовочные файлы:
#include <AknLists.h>
#include <AknIconArray.h>
#include <eikclbd.h>

Загрузка списка из ресурсов приложения

Теперь рассмотрим второй способ — загрузка из ресурсов приложения.

Первое, что вы должны сделать, — это описать список в ресурсах приложения. Список описывается структурой LISTBOX, в которой обычно определяется только два поля: flags и items. В поле флаг указывается константа, определяющая тип списка: EAknListBoxSelectionList, EAknListBoxMultiselectionList, EAknListBoxMarkableList или EAknListBoxViewerFlags. В поле items — указатель на массив пунктов списка. Для нашего примера в rss-файл надо добавить следующее:
RESOURCE LISTBOX r_example_listbox {
flags = EAknListBoxSelectionList;
array_id = r_example_listbox_items;
}
RESOURCE ARRAY r_example_listbox_items {
items = {
LBUF { txt = "0\tItem 1\t\t"; },
LBUF { txt = "1\tItem 2\t\t"; },
LBUF { txt = "2\tItem 3\t\t"; }
};
}

Создание списка, как и в предыдущем примере, происходит в конструкторе класса, порожденного от CAknAppUi. Необходимо сделать следующее: 1) создать экземпляр класса списка:
iList = new (ELeave) CAknSingleGraphicStyleListBox;
iList->SetMopParent(this);
TResourceReader rr;
CEikonEnv::Static()->CreateResourceReaderLC(rr, R_EXAMPLE_LISTBOX);
iList->ConstructFromResourceL(rr);
CleanupStack::PopAndDestroy();
iList->SetRect(ClientRect());
2) создать, если необходимо, полосу прокрутки (см. предыдущий пример);
3) создать массив иконок (если вы используете список с иконками) и добавить его в список (см. предыдущий пример);
4) активировать список и установить его в качестве центральной панели (см. предыдущий пример).

Работа со списком

Все классы списков в качестве одного из предков имеют класс CEikListBox, в котором собраны почти все функции для работы со списками. Наиболее часто в ходе работы возникает необходимость узнать, какой пункт списка в данный момент выбран. Функция CurrentItemIndex() класса CEikListBox позволяет получить индекс выбранного пункта, а функция SetCurrentItemIndex( TInt aItemIndex ) — сделать выбранным другой пункт. Если вы определили список как EAknListBoxMultiselectionList, то для получения массива индексов помеченных пунктов используется функция SelectionIndexes(). В ходе работы приложения вы можете добавлять, удалять и изменять пункты списка. Для доступа к элементам списка используется класс CTextListBoxModel, указатель на который можно получить с помощью функции Model() класса CEikListBox. Класс CTextListBoxModel позволяет получить доступ к массиву пунктов списка (но не к иконкам), который вы можете редактировать по своему усмотрению. Добавить новый элемент в список через класс CTextListBoxModel можно следующим образом:

MDesCArray* textArray = iList->Model()->ItemTextArray();
CDesCArray* itemList = static_cast<CDesCArray*>(textArray);
itemList->AppendL(_L("1\tNew item\t\t"));
iList->HandleItemAdditionL();
Удалить элемент из списка:
MDesCArray* textArray = iList->Model()->ItemTextArray();
CDesCArray* itemList = static_cast<CDesCArray*>(textArray);
itemList->Delete(0, 1); // удалить один элемент с индексом 0
iList->HandleItemRemovalL();
В этом примере удаляется пункт с индексом 0. Если надо поменять текст, номер или иконку пункта, сделать это можно так (изменяем элемент с индексом 2):
MDesCArray* textArray = iList->Model()->ItemTextArray();
CDesCArray* itemList = static_cast<CDesCArray*>(textArray);
(*itemList)[2] = _L("1\tNew item 2\t\t");
iList->HandleItemAdditionL();

Редакторы

Вторым наиболее часто используемым органом управления являются различные редакторы. В S60 есть следующие:
CEikEdwin — простой одно- или многострочный редактор текста (структура в ресурсах — EDWIN);
CEikGlobalTextEditor — редактор текста, поддерживающий форматирование (структура в ресурсах — GTXTED);
CEikRichTextEditor — редактор текста, поддерживающий форматирование и вставку рисунков (структура в ресурсах — RTXTED);
CAknIntegerEdwin — редактор ввода целых чисел (структура в ресурсах — NUMBER_EDITOR);
CEikFixedPointEditor — редактор ввода чисел с фиксированной точкой;
CEikFloatingPointEditor — редактор ввода чисел с плавающей точкой типа TReal;
CEikDateEditor — редактор ввода даты (структура в ресурсах — DATE_EDITOR);
CEikTimeEditor — редактор ввода времени (структура в ресурсах — TIME_EDITOR);
CEikTimeAndDateEditor — редактор ввода даты и времени (структура в ресурсах — TIME_AND_DATE _EDITOR);
CEikSecretEditor — редактор текста для ввода различных паролей (вводимый текст отображается звездочками).

Работа с редакторами довольно проста за исключением CEikGlobalTextEditor и CEikRichTextEditor (его рассмотрим в одной из следующих статей). Рассмотрим редакторы на примере CEikEdwin. Создается редактор текста, как и список, двумя способами: во время выполнения программы и путем загрузки из ресурсов. Во время выполнения программы редактор создается следующим образом:
iEditor = new (ELeave) CEikEdwin;
iEditor->SetMopParent( this );
iEditor->ConstructL();
iEditor->SetRect(ClientRect());
iEditor ->ActivateL();
AddToStackL(iEditor);

Если надо организовать создание путем загрузки из ресурсов, делается это так:
iEditor = new (ELeave) CEikEdwin;
iEditor->SetMopParent( this );
TResourceReader rr;
CEikonEnv::Static()->CreateResourceReaderLC(rr, R_EXAMPLE_EDWIN);
iEditor->ConstructFromResourceL(rr);
CleanupStack::PopAndDestroy();
iEditor->SetRect(ClientRect());
iEditor ->ActivateL();
AddToStackL(iEditor);

Здесь R_EXAMPLE_EDWIN — это идентификатор структуры EDWIN в ресурсах. Пример структуры EDWIN:
RESOURCE EDWIN r_example_edwin {
maxlength=1024;
}

В данном примере определена только максимальная длина текста. Для того, чтобы установить начальный текст для редактора, воспользуйтесь функцией SetTextL() класса CEikEdwin, а для того, чтобы прочитать текст из редактора — GetText() или GetTextInHBufL(). Функцию GetText() обычно используют, когда длина редактируемого текста ограничена. Например:
TBuf<1024> text;
iEditor->GetText(text);

Если же длина редактируемого текста неограниченна, удобнее использовать функцию GetTextInHBufL(). Она сама выделяет память под буфер и помещает туда текст, т.е.
HBufC *text = iEditor->GetTextInHBufL();
эквивалентно
HBufC *text = HBufC::NewL(iEditor->TextLength());
iEditor->GetText(*text);

Другие стандартные органы управления

Кроме списков и редакторов, есть еще несколько других стандартных органов управления. Наиболее часто используемые — слайдер (класс CAknSlider, структура в ресурсах — SLIDER), представляющий собой полоску с ползунком, и регулятор уровня (класс CAknVolumeControl, структура в ресурсах — VOLUME). Работа с ними довольно проста, и трудностей у вас возникнуть не должно. Если вы писали приложения для Windows, то наверняка имели дело с такими органами управления, как checkbox, radiobutton и combobox. В S60 таких органов управления нет (хотя в Symbian некоторые такие классы есть — например, CEikCheckbox, — но в S60 они запрещены). Вместо них должны использоваться различные варианты списков. Надо сказать, что в качестве центральной панели часто используются списки — CEikEdwin, CEikGlobalTextEditor и CEikRichTextEditor — и почти никогда не используются остальные органы управления, которые я упоминал. В основном они предназначены для использования в диалогах, которые и будут темой следующей статьи.

Алексей Аношенко


Компьютерная газета. Статья была опубликована в номере 04 за 2007 год в рубрике mobile

©1997-2024 Компьютерная газета