---------------------------------------------定义设置列表(Setting List)对应的Symbian类-----------------------------
class CExampleSettingList : public CAknSettingItemList
{
.......
public:
CAknSettingItem* CreateSettingItemL (TInt aSettingId); // must Overload this func.
private:
CSettingsData &iSettingsData; /* Reference to data owned by AppUi */
......
}
CAknSettingItem * CExampleSettingList::CreateSettingItemL (TInt aIdentifier)
{
// method is used to create specific setting item as required at run-time.
// aIdentifier is used to determine what kind of setting item should be
// created
CAknSettingItem* settingItem = NULL;
switch (aIdentifier)
{
case ESettingText: //--文本编辑器对应的C++类(系统自带类)
settingItem = new (ELeave) CAknTextSettingItem (aIdentifier,
iSettingsData.Text());
break;
case ESettingRadioBtn: //单选按钮对应的C++类(系统自带类)
settingItem = new (ELeave) CAknEnumeratedTextPopupSettingItem (
aIdentifier, iSettingsData.iEnumeration);
break;
case ESettingCheckbox: // 多选框对应的C++类(用户自定义的类型)
settingItem = new (ELeave) CSettingAppCheckBoxSettingItem (
aIdentifier, (iSettingsData.CheckboxArray()));
break;
case ESettingVolume: // 音量调节对应的C++类(系统自带类)
settingItem = new (ELeave) CAknVolumeSettingItem (
aIdentifier, iSettingsData.Volume());
break;
case ESettingSlider: // 滑动条对应的C++类(系统自带类)
settingItem = new (ELeave) CAknSliderSettingItem (
aIdentifier, iSettingsData.Slider());
break;
case ESettingBinary: // 开关按钮对应的C++类(系统自带类)
settingItem = new (ELeave) CAknBinaryPopupSettingItem (
aIdentifier, iSettingsData.Binary());
break;
case ESettingSecret: // 密码编辑器对应的C++类(系统自带类)
settingItem = new (ELeave) CAknPasswordSettingItem (
aIdentifier, CAknPasswordSettingItem::EAlpha,
iSettingsData.SecretText());
break;
case ESettingNumeric: // 数字编辑器对应的C++类(系统自带类)
settingItem = new (ELeave) CAknTextSettingItem (
aIdentifier, iSettingsData.NumericText());
break;
case ESettingDate:// 日期设置控件对应的C++类(系统自带类)
settingItem = new (ELeave) CAknTimeOrDateSettingItem (
aIdentifier, CAknTimeOrDateSettingItem::EDate,
iSettingsData.Date());
break;
case ESettingTime: // 时间设置控件对应的C++类(系统自带类)
settingItem = new (ELeave) CAknTimeOrDateSettingItem (
aIdentifier, CAknTimeOrDateSettingItem::ETime,
iSettingsData.Time());
break;
case ESettingIp:// IP设置控件对应的C++类(系统自带类)
settingItem = new (ELeave) CAknIpFieldSettingItem (
aIdentifier, iSettingsData.IpAddress());
break;
default:
break;
}
return settingItem;
}
---------------------------------------------定义设置项(Setting Item)对应的Symbian类----------------------------
/**
* Class: CSettingAppCheckBoxSettingItem
*
* Discussion: Subclassed from CAkenEnumeratedTextSettingItem. This class is
* used to provide a text indication of the state of multiple
* boolean flags.
*/
class CSettingAppCheckBoxSettingItem : public CAknEnumeratedTextSettingItem
{
public:
/**
* Function : CSettingAppCheckBoxSettingItem
* Params : aIdentifier - Resource Id for the setting item
* aExternalValueArray - array of external values, the state
* of which will be reflected in the display.
*/
CSettingAppCheckBoxSettingItem(TInt aIdentifier, CArrayFix<TInt>& aExternalValueArray );
~CSettingAppCheckBoxSettingItem();
/**
* Function : LoadL
*
* Discussion : Inherited from CAknSettingItem - loads values from external
* data. Called at construction, but can also be called as
* required.
*
*/
void LoadL();
/**
* Function : StoreL
*
* Discussion : Inherited from CAknSettingItem - transfers internal values
* back to external storage.
*
*/
void StoreL();
/**
* Function : EditItemL
*
* Discussion : Inherited from CAknSettingItem - launches the setting page
*
* Params : aCalledFromMenu - ignored in code.
*/
void EditItemL( TBool aCalledFromMenu );
/**
* Function : CompleteConstructionL
*
* Discussion : Called by framework to complete construction. Second-phase
* constructor.
*/
void CompleteConstructionL();
/**
* Function : SettingTextL
*
* Discussion : Obtains the current setting text for the item.
*
* Returns : A descriptor containing the setting text
*
*/
const TDesC& SettingTextL();
private:
/**
* Function : SetTextRepresentationL
*
* Discussion : Updates the internal text representation string according
* to the current states of the items stored within
* iSelectionItemListData.
*
*/
void SetTextRepresentationL() ;
private:
/**
* Selection item list. This acts as the internal
* representation of the check box list
* OWNED by this class.
*/
CSelectionItemList* iSelectionItemListData;
/**
* Reference to the external array of integers
* NOT OWNED by this class
*/
CArrayFix<TInt>& iExternalValueArray;
/**
* Internal text represenation of data
* OWNED by this class
*/
HBufC* iTextRepresentation; // Owned
};
CSettingAppCheckBoxSettingItem::CSettingAppCheckBoxSettingItem(TInt aIdentifier, CArrayFix<TInt>& aValueList )
: CAknEnumeratedTextSettingItem(aIdentifier), iExternalValueArray(aValueList)
{
}
CSettingAppCheckBoxSettingItem::~CSettingAppCheckBoxSettingItem()
{
if ( iSelectionItemListData )
{
iSelectionItemListData->ResetAndDestroy();
delete iSelectionItemListData;
}
delete iTextRepresentation;
}
#define KSettingAppLanguageCodeGranularity 5
void CSettingAppCheckBoxSettingItem::CompleteConstructionL()
{
CAknEnumeratedTextSettingItem::CompleteConstructionL();
// Now do type specific stuff
iSelectionItemListData = new (ELeave) CSelectionItemList( KSettingAppLanguageCodeGranularity );
// Loop over the array of integers
TInt count = EnumeratedTextArray()->Count();
TInt index;
for ( index = 0; index < count; ++index )
{
CSelectableItem* selectionItem = new(ELeave)CSelectableItem( *(EnumeratedTextArray()->At(index)->Value()), EFalse );
CleanupStack::PushL(selectionItem);
selectionItem->ConstructL();
iSelectionItemListData->AppendL(selectionItem); // selectionItem is now "owned" by app. Must be ResetAndDestroyed
CleanupStack::Pop(); // selectionItem
}
}
void CSettingAppCheckBoxSettingItem::LoadL()
{
// Set true in the selection array if the value is in the array
SetTextRepresentationL();
}
void CSettingAppCheckBoxSettingItem::StoreL()
{
// Record how many integers there are in the array (This number will be deleted at the end)
}
void CSettingAppCheckBoxSettingItem::EditItemL( TBool /* aCalledFromMenu */)
{
CAknCheckBoxSettingPage* dlg = new ( ELeave )CAknCheckBoxSettingPage(R_CHECKBOX_PAGE /* R_RADIO_BUTTON_SETTING_PAGE is system built in resource*/, iSelectionItemListData);
if ( dlg->ExecuteLD(CAknSettingPage::EUpdateWhenChanged) )
{ // Display the resuklt
/*
TInt nItems = iSelectionItemListData->Count();
TBuf<40> text;
for (TInt ii=0; ii<nItems; ii++)
{
if ( (*iSelectionItemListData)[ii]->SelectionStatus() )
{
TBuf<4> newtext;
newtext.Format(_L("%d,"), ii );
text.Append( newtext );
}
}
User::InfoPrint( text );
*/
SetTextRepresentationL();
UpdateListBoxTextL();
// StoreL();
}
}
const TDesC& CSettingAppCheckBoxSettingItem::SettingTextL()
{
if ( iExternalValueArray.Count() == 0
|| !iTextRepresentation ) return EmptyItemText();
return *(iTextRepresentation);
}
void CSettingAppCheckBoxSettingItem::SetTextRepresentationL()
{
delete iTextRepresentation;
iTextRepresentation = 0;
TInt nItems = iSelectionItemListData->Count();
TBuf<100> text;
CDesCArray* textArray = /*iCoeEnv->*/CCoeEnv::Static()->ReadDesCArrayResourceL( R_CHECKBOXEDITOR_TEXTS );
CleanupStack::PushL(textArray);
TBool AddComma=EFalse;
_LIT(KRokaComma,", ");
for (TInt ii=0; ii<nItems; ii++)
{
if ( (*iSelectionItemListData)[ii]->SelectionStatus() )
{
/*
TBuf<4> newtext;
newtext.Format(_L("%d,"), ii );
text.Append( newtext );
*/
if (AddComma)text.Append(KRokaComma);
text.Append(textArray->MdcaPoint(ii) );
AddComma=ETrue;
}
}
CleanupStack::PopAndDestroy(); // textArray
iTextRepresentation = text.AllocL();
}
------------------------将SettingList控件集成到一个视图中去---------------
class CSettingListView : public CAknView
{
...
/**
* Often, the setting list would be the child control of some container.
* In this case, as only a single control is used, there is no container
* class.
*
* This control is owned by the SettingListView and must be deleted in
* the destructor.
*/
CExampleSettingList* iSettingList;
/**
* the data which will be modified by the settings list.
*/
CSettingsData& iSettingsData;
};
在BREW中要做一个配置窗口是非常麻烦的事情,而S60的配置列表却相当方便。尤其是利用资源文件来构造配置页,在RSS中写的东西有点复杂但是代码却简化了不少。
先看简单的代码,需要自己构造一个SettingItemList类派生于CAknSettingItemList即可:
class CUniNewsSettingItemList: public CAknSettingItemList
{
public:
void ConstructL();
CAknSettingItem* CreateSettingItemL( TInt aIdentifier );
public:
TBool iDown;
TTime iTime;
} ;
其中,iDown和iTime是两个需要配置的内容(这个例子中我需要在配置页让用户选择“是否自动下载”以确定“自动下载的时间”。)
然后在实现代码中这样:
{
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中的描述,相对于代码来说,这稍有点复杂了。
{
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 ;
};
}
我也是按网上找到的资料来改写的。虽然看上去有点多,不过看明白了其实还是相当有规律的,应该比在代码中写大堆的东西要简便一点。
其实也可以完全在代码中动态生成配置页而不依靠资源文件中的描述。但是那样做太复杂了,我以后再去研究吧。