数组是一个很基本的东西了,但是在Symbian中也做了比较人性化的封装,让我们可以省却不少代码,当然也让我们这些新手有点摸不着头脑。
三个类比较实用,需要掌握:TFixedArray、RArray和RPointerArray。
TFixedArray
它是最类似于我们平时使用的数组,从概念上或者从使用上都非常类似。
//声明
TFixedArray<TGridCell,81> iGrid;
//使用
void CSuDoScAppView::InitGrid()
{
for(TInt i=0;i<81;i++)
{
if(iCurQs->data[i]==0)
{
iGrid[i].state=TGridCell::ECSTATE_EMPTY;
}
else
{
iGrid[i].state=TGridCell::ECSTATE_FIXED;
}
iGrid[i].value=iCurQs->data[i];
for(TInt j=0;j<9;j++) iGrid[i].tries[j]=0;
}
if(iHeart!=NULL)...{
iHeart->Cancel();
iTime=0;
iHeart->Start(ETwelveOClock,this);
}
}
把它当成普通的数组来用就OK了,一般也就是用它重载的运算符[]和Count(),不需new也不需要delete。
RArray
从名字上看它以R开头,至少说明一点,在使用完后我们需要将它Close掉。在使用上也比较简单,类似于ArrayList吧。比如下面代码:
//声明
RArray<TQuestion> iList;
//使用
void CSuDoScAppCtrol::LoadQuestions()
{
RFile file;
TBuf8<4> bufC4;
TBuf8<81> bufC81;
if(KErrNone==file.Open(iFs,KTiDataFile,EFileRead))
{
file.Read(bufC4,4);
TUint len=((TUint)bufC4[3]<<24)+((TUint)bufC4[2]<<16)+((TUint)bufC4[1]<<8)+(TUint)bufC4[0];
for(int i=0;i<len;i++)...{
TQuestion ti;
bufC4.FillZ();
file.Read(bufC4,4);
ti.code=((TUint)bufC4[3]<<24)+((TUint)bufC4[2]<<16)+((TUint)bufC4[1]<<8)+(TUint)bufC4[0];
bufC4.FillZ();
file.Read(bufC4,4);
ti.time=0;
bufC81.FillZ();
file.Read(bufC81,81);
for(TInt i=0;i<81;i++)ti.data[i]=bufC81[i];
iList.Append(ti);
}
file.Close();
}
}
除了在析构函数中需要iList.Close()以外,事先不需要做什么初始化工作,一个个的Append进去就可以了。它也重载了运算符[],可以简单地访问其中的元素。
RPointerArray
名字上说明它与指针有关,的确它与RArray的差别在于它不是保存对象的副本而是保存对象的指针。所以,使用上需要自己负责将元素删除。
//声明
RPointerArray<CFbsBitmap> iThumbNormal;
//使用
for(TInt i=0,j=0;i<9;i++,j+=2)...{
CFbsBitmap * b=NULL;
CFbsBitmap * c=NULL;
AknIconUtils::CreateIconL(b,c,iMFileName,EMbmSudoscY1+j,EMbmSudoscY1+j+1);
AknIconUtils::SetSize(b, TSize(22, 22));
AknIconUtils::SetSize(c, TSize(22, 22));
iThumbNormal.AppendL(b);
iThumbNormalMask.AppendL(c);
}
//删除
for(TInt i=0;i<9;i++)...{
delete iThumbNormal[i];
delete iThumbNormalMask[i];
}
iThumbNormal.Close();
此外,虽然SDK中我们也看到许多CDesXXXX的数组类,但是我觉得上面三个类应该可以应付我们大多数的场合了。
在BREW中要做一个配置窗口是非常麻烦的事情,而S60的配置列表却相当方便。尤其是利用资源文件来构造配置页,在RSS中写的东西有点复杂但是代码却简化了不少。
先看简单的代码,需要自己构造一个SettingItemList类派生于CAknSettingItemList即可:
class CUniNewsSettingItemList: public CAknSettingItemList
{
public:
void ConstructL();
CAknSettingItem* CreateSettingItemL( TInt aIdentifier );
public:
TBool iDown;
TTime iTime;
};
其中,iDown和iTime是两个需要配置的内容(这个例子中我需要在配置页让用户选择“是否自动下载”以确定“自动下载的时间”。)
然后在实现代码中这样:
void CUniNewsSettingItemList::ConstructL()
{
CAknSettingItemList::ConstructFromResourceL( R_CFG_ITEM_LIST );
}
CAknSettingItem* CUniNewsSettingItemList::CreateSettingItemL(TInt aIdentifier)
{
CAknSettingItem* settingItem = NULL;
switch (aIdentifier)
{
case EMySettingItemBinary:
settingItem =
new (ELeave) CAknBinaryPopupSettingItem(
aIdentifier, iDown);
break;
case EMySettingItemTime:
settingItem =
new (ELeave) CAknTimeOrDateSettingItem(
aIdentifier,CAknTimeOrDateSettingItem::ETime,iTime);
break;
}
return settingItem;
}
在ConstructL中简单地调用基类的函数从资源中生成配置页,而在CreateSettingItemL函数里根据aIdentifier去资源文件中读取相应的描述来生成配置项。
创建一个BOOL配置项可用CAknBinaryPopupSettingItem,它在构造函数第二个参数就是iDown成员,这样关联一下就把这个配置项与成员iDown关联上了,同理,创建一个
CAknTimeOrDateSettingItem实例,与iTime成员关联上。相关的配置项有很多,在SDK中可以找到它们的说明:API Reference Guide/C++API Reference/UI Framework/Setting Pages API。
代码差不多就这样了,使用与普通的ListBox没什么两样,只需要在保存和加载时注意一下即可。
在显示配置页时,记得先iListBox->LoadSettingsL()一下就让iListBox从成员变量中加载数据,而在保存时也同样iListBox->StoreSettingsL()让成员变量从配置页中得到配置结果。
现在来看看RSS中的描述,相对于代码来说,这稍有点复杂了。
RESOURCE AVKON_VIEW r_view_cfg
{
cba = R_AVKON_SOFTKEYS_DONE_CANCEL;
}
RESOURCE AVKON_SETTING_ITEM_LIST r_cfg_item_list
{
flags = EAknSettingItemNumberedStyle;
title = qtn_cfg_title;
initial_number = 1;
items =
{
AVKON_SETTING_ITEM
{
identifier = EMySettingItemBinary;
setting_page_resource = r_binary_setting_page;
associated_resource = r_popup_setting_binary_texts;
name = qtn_cfg_autodown;
},
AVKON_SETTING_ITEM
{
identifier = EMySettingItemTime;
setting_page_resource = r_time_setting_page;
name = qtn_cfg_autotime;
}
};
}
RESOURCE AVKON_SETTING_PAGE r_binary_setting_page
{
number = 1;
label = qtn_cfg_autodown;
type = EAknCtPopupSettingList;
editor_resource_id = r_binary_popup_setting_list;
}
RESOURCE AVKON_POPUP_SETTING_TEXTS r_popup_setting_binary_texts
{
flags = 0;
setting_texts_resource = r_on_off_texts;
popped_up_texts_resource = r_popped_up_on_off_texts;
}
RESOURCE ARRAY r_on_off_texts
{
items =
{
AVKON_ENUMERATED_TEXT { value = 1; text = qtn_cfg_autodown_on; },
AVKON_ENUMERATED_TEXT { value = 0; text = qtn_cfg_autodown_off; }
};
}
RESOURCE ARRAY r_popped_up_on_off_texts
{
items =
{
LBUF { txt = qtn_cfg_autodown_on; },
LBUF { txt = qtn_cfg_autodown_off; }
};
}
RESOURCE POPUP_SETTING_LIST r_binary_popup_setting_list
{
flags= 0;
}
RESOURCE AVKON_SETTING_PAGE r_time_setting_page
{
number = 2;
label = qtn_cfg_autotime;
type = EEikCtTimeEditor;
editor_resource_id = r_settinglist_time_editor;
}
RESOURCE TIME_EDITOR r_settinglist_time_editor
{
minTime = TIME
{
second = 0;
minute = 0;
hour = 0;
};
maxTime = TIME
{
second = 59;
minute = 59;
hour = 23;
};
}
我也是按网上找到的资料来改写的。虽然看上去有点多,不过看明白了其实还是相当有规律的,应该比在代码中写大堆的东西要简便一点。
其实也可以完全在代码中动态生成配置页而不依靠资源文件中的描述。但是那样做太复杂了,我以后再去研究吧。