To use forms, the dialog resource (RESOURCE DIALOG
) must
be defined in the application resource file and a matching CAknForm
-based
class must be provided.
Example data structure TMyData
is used to demonstrate
the usage of most typical data fields in forms.
struct TMyData { public: // data TBuf<256> iText; TBuf<256> iGlobalText; TBuf<256> iRichText; TInt iNumber; TInt iInteger; TReal iFloat; TInt iFix; TTime iDate; TTime iTime; TTimeIntervalSeconds iDuration; TBuf<4> iNumPwd; TBuf<8> iAlphaPwd; TInetAddr iIpAddr; MAknQueryValue* iPopupVal; TInt iPopupTextIndex; TInt iSliderVal; };
The class CMyForm
is used to display and edit the data.
class CMyForm : public CAknForm { public: // construction CMyForm( TMyData& aData ); virtual ~CMyForm(); public: // from CAknForm void DynInitMenuPaneL( TInt aResourceId, CEikMenuPane* aMenuPane ); void ProcessCommandL( TInt aCommandId ); TBool SaveFormDataL(); void DoNotSaveFormDataL(); void AddItemL() ; void PreLayoutDynInitL(); MEikDialogPageObserver::TFormControlTypes ConvertCustomControlTypeToBaseControlType( TInt aControlType ) const; private: void LoadFormDataL() ; private: // data TMyData& iData; TInt iAddedItemId; };
Since a form is a special dialog, its resource definition is within a DIALOG
resource,
that is, the dialog structure has the LLINK
form as a member.
STRUCT DIALOG { LONG flags = 0; LTEXT title = ""; LLINK pages = 0; LLINK buttons = 0; STRUCT items[]; LLINK form = 0; }
When considering forms, the important members of the DIALOG
structure
are:
flags
, which specifies the whole form style. The flag
parameters
are defined in the eikon.hrh file.
pages
, which is a reference to an ARRAY
of PAGE
.
Used only in multi-page forms (see Multi-page form).
For single-page forms, this should not be specified.
buttons
, which specifies softkeys.
form
, which is a reference to the FORM
structure
described later. Used in single-page forms. For multi-page forms, this should
not be specified.
See document S60 3.1 Dialogs API Specification
for more
information on other DIALOG
structure members.
STRUCT FORM { WORD flags = 0; STRUCT items[]; }
The FORM
structure member flags
can be
used to specify the style of the form. The default setting is single-line
display, and the predefined values are as follows:
Flag | Description |
---|---|
EEikFormUseDoubleSpacedFormat |
Double-line display. |
EEikFormHideEmptyFields |
Makes empty data fields invisible. |
EEikFormShowBitmaps |
Displays a bitmap on a label. |
EEikFormEditModeOnly |
Displays the form in edit mode only. |
EEikFormShowEmptyFields |
Displays single-line display (default). |
Form fields are described with the structure DLG_LINE
in
the member items of the FORM
structure.
STRUCT DLG_LINE { WORD type; LTEXT prompt; WORD id = 0; LONG itemflags = 0; STRUCT control; LTEXT trailer = ""; LTEXT bmpfile = ""; WORD bmpid = 0xffff; WORD bmpmask; LTEXT tooltip = ""; }
The important members of this structure are:
EEikCtEdwin
, EEikCtNumberEditor
, EEikCtDateEditor
, EEikCtTimeEditor
, EEikCtDurationEditor
, EEikCtSecretEd
,
or EAknCtSlider
. Types are defined in the eikon.hrh or avkon.hrh files.
For details on the resource structures defining individual controls, see document S60
3.1 Editors API Specification
.
prompt
, which specifies the field label.
id
, which specifies the control ID of the application.
Within the application, the ID is used to reference the dialog line. The ID
must be defined in the application's HRH file. Each dialog line must have
a unique ID; otherwise the application panics when the dialog is executed.
itemflags
, such as EEikDlgItemTakesEnterKey
or EEikDlgItemOfferAllHotKeys
.
control
, which specifies the field control. Controls
are defined in HRH files.
bmpfile
, which specifies the bitmap filename.
bmpid
, which specifies the icon image ID.
bmpmask
, which specifies the icon mask ID.
The following resource defines a form for viewing and editing TMyStruct
data
in a single page.
RESOURCE DIALOG r_my_dialog { flags = EEikDialogFlagNoBorder | EEikDialogFlagNoDrag | EEikDialogFlagNoTitleBar | EEikDialogFlagFillAppClientRect | EEikDialogFlagCbaButtons | EEikDialogFlagWait; buttons = R_AVKON_SOFTKEYS_OPTIONS_BACK; form = r_my_form; } RESOURCE FORM r_my_form { flags = EEikFormUseDoubleSpacedFormat; items = { DLG_LINE { type = EEikCtEdwin; prompt = "Text" ; id = EMyAppControlIdTextEd; itemflags = EEikDlgItemTakesEnterKey; control = EDWIN { flags = KMultiLineExpandingEditorFlags | EEikEdwinNoLineOrParaBreaks; maxlength = 256; width = 6; }; }, DLG_LINE { type = EEikCtGlobalTextEditor; prompt = "Global text"; id = EMyAppControlIdGlobalTextEd; itemflags = EEikDlgItemTakesEnterKey; control = GTXTED { width = 10; height = 17; textlimit = 256; flags = KMultiLineExpandingEditorFlags; max_view_height_in_lines = 2; }; }, DLG_LINE { type = EEikCtRichTextEditor; prompt = "Rich text"; id = EMyAppControlIdRichTextEd; itemflags = EEikDlgItemTakesEnterKey; control = RTXTED { width = 10; height = 17; textlimit = 256; flags = KMultiLineExpandingEditorFlags; max_view_height_in_lines = 3; }; }, DLG_LINE { type = EEikCtNumberEditor; prompt = "Number" ; id = EMyAppControlIdNumberEd ; control = NUMBER_EDITOR { min = 0; max = 999; }; }, DLG_LINE { type = EAknCtIntegerEdwin; prompt = "Integer edwin" ; id = EMyAppControlIdIntegerEd; itemflags = EEikDlgItemTakesEnterKey; control = AVKON_INTEGER_EDWIN { maxlength = 10; min = 0; max = 999; }; }, DLG_LINE { type = EEikCtFlPtEd; prompt = "Floating point" ; id = EMyAppControlIdFloatEd; itemflags = EEikDlgItemTakesEnterKey; control = FLPTED { maxlength = 10; min = 0; max = 999; }; }, DLG_LINE { type=EEikCtFxPtEd; prompt = "Fixed point" ; id = EMyAppControlIdFixEd; itemflags = EEikDlgItemTakesEnterKey; control = FIXPTED { min = 0; max = 99999; decimalplaces = 2; }; }, DLG_LINE { type = EEikCtDateEditor; prompt = "Date" ; id = EMyAppControlIdDateEd ; itemflags = EEikDlgItemTakesEnterKey; control = DATE_EDITOR { minDate = DATE { year = 1900; }; maxDate= DATE { year = 2100; }; flags = 0; }; }, DLG_LINE { type = EEikCtTimeEditor; prompt = "Time"; id = EMyAppControlIdTimeEd; itemflags = EEikDlgItemTakesEnterKey; control = TIME_EDITOR { minTime = TIME {}; maxTime = TIME { second = 59; minute = 59; hour = 23; }; flags = 0; }; }, DLG_LINE { type = EEikCtDurationEditor; prompt = "Duration"; id = EMyAppControlIdDurationEd; itemflags = EEikDlgItemTakesEnterKey; control = DURATION_EDITOR { minDuration = DURATION {}; maxDuration = DURATION { seconds = 3599; }; flags = 0; }; }, DLG_LINE { type = EAknCtNumericSecretEditor; prompt = "Secret number"; id = EMyAppControlIdNumPwdEd; itemflags = EEikDlgItemTakesEnterKey; control = NUMSECRETED { num_code_chars = 4; }; }, DLG_LINE { type = EEikCtSecretEd; prompt = "Secret text"; id = EMyAppControlIdAlphaPwdEd; itemflags = EEikDlgItemTakesEnterKey; control = SECRETED { num_letters = 8; }; }, DLG_LINE { type = EAknCtIpFieldEditor; prompt = "IP address"; id = EMyAppControlIdIpAddrEd; itemflags = EEikDlgItemTakesEnterKey; control = IP_FIELD_EDITOR { min_field_values = IP_FIELD { first_field = 0; second_field = 0; third_field = 0; fou?th_field = 0; }; max_field_values = IP_FIELD { first_field = 255; second_field = 255; third_field = 255; fourth_field = 255; }; flags = 0; }; }, DLG_LINE { type = EAknCtPopupField; prompt = "Popup field"; id = EMyAppControlIdPopupField; itemflags = EEikDlgItemTakesEnterKey; control = POPUP_FIELD { flags = EAknPopupFieldFlagAllowsUserDefinedEntry; width = 50; other = "Other"; empty = "No items"; invalid = "Invalid item"; }; }, DLG_LINE { type = EAknCtPopupFieldText; prompt = "Popup field text"; id = EMyAppControlIdPopupFieldText; itemflags = EEikDlgItemTakesEnterKey; control = POPUP_FIELD_TEXT { textarray = r_my_list_popup_items; popupfield = POPUP_FIELD {}; active = 0; }; }, DLG_LINE { type = EAknCtSlider; prompt = "Slider"; id = EMyAppControlIdSlider; itemflags = EEikDlgItemTakesEnterKey; control = SLIDER { layout = EAknFormSliderLayout2; minvalue = 0; maxvalue = 20; step = 2; valuetype = EAknSliderValueNone; minlabel = "few"; maxlabel = "many"; valuelabel = "Slider value"; }; } }; } RESOURCE ARRAY r_my_list_popup_items { items = { LBUF { txt = "Monday"; }, LBUF { txt = "Tuesday"; }, LBUF { txt = "Wednesday"; }, LBUF { txt = "Thursday"; }, LBUF { txt = "Friday"; }, LBUF { txt = "Saturday"; }, LBUF { txt = "Sunday"; } }; }
Multi-page forms also use the DIALOG
resource structure,
but DIALOG
structure member pages
are needed
as a reference to an ARRAY
of PAGE
. The PAGE
structure
is as follows:
STRUCT PAGE { WORD id = 0; LTEXT text; LTEXT bmpfile = ""; WORD bmpid = 0xffff; WORD bmpmask; LLINK lines = 0; LLINK form = 0; WORD flags = 0; }
The following members are concerned with forms in the PAGE
structure:
id
, which specifies the page ID of an application.
text
, which specifies the title string of tabs.
form
, which is a reference to the FORM
structure.
The following resource defines a form for viewing and editing TMyStruct
data
in a multi-page dialog. The DLG_LINE
structures are identical
to the single-page example (except that the first page is decorated with icons).
RESOURCE DIALOG r_my_multipage_dialog { flags = EEikDialogFlagNoBorder | EEikDialogFlagNoDrag | EEikDialogFlagNoTitleBar | EEikDialogFlagFillAppClientRect | EEikDialogFlagCbaButtons | EEikDialogFlagWait; buttons = R_AVKON_SOFTKEYS_OPTIONS_BACK ; pages = r_my_pages; } RESOURCE ARRAY r_my_pages { items = { PAGE { text = "text"; id = EMyAppPage1 ; form = r_my_form_1 ; }, PAGE { text = "number"; id = EMyAppPage2 ; form = r_my_form_2 ; }, PAGE { text = "misc"; id = EMyAppPage3 ; form = r_my_form_3 ; } }; } RESOURCE FORM r_my_form_1 { flags = EEikFormUseDoubleSpacedFormat | EEikFormShowBitmaps; items = { DLG_LINE { type = EEikCtEdwin; prompt = "Text" ; id = EMyAppControlIdTextEd; itemflags = EEikDlgItemTakesEnterKey; control = EDWIN { flags = KMultiLineExpandingEditorFlags | EEikEdwinNoLineOrParaBreaks; maxlength = 256; width = 6; }; bmpfile = AVKON_ICON_FILE; bmpid = EMbmAvkonQgn_prop_folder_small; bmpmask = EMbmAvkonQgn_prop_folder_small_mask; }, DLG_LINE { type = EEikCtGlobalTextEditor; prompt = "Global text"; id = EMyAppControlIdGlobalTextEd; itemflags = EEikDlgItemTakesEnterKey; control = GTXTED { width = 10; height = 17; textlimit = 256; flags = KMultiLineExpandingEditorFlags; max_view_height_in_lines = 2; }; bmpfile = AVKON_ICON_FILE; bmpid = EMbmAvkonQgn_prop_folder_small; bmpmask = EMbmAvkonQgn_prop_folder_small_mask; }, DLG_LINE { type = EEikCtRichTextEditor; prompt = "Rich text"; id = EMyAppControlIdRichTextEd; itemflags = EEikDlgItemTakesEnterKey; control = RTXTED { width = 10; height = 17; textlimit = 256; flags = KMultiLineExpandingEditorFlags; max_view_height_in_lines = 3; }; bmpfile = AVKON_ICON_FILE; bmpid = EMbmAvkonQgn_prop_folder_small; bmpmask = EMbmAvkonQgn_prop_folder_small_mask; } }; } RESOURCE FORM r_my_form_2 { flags = EEikFormUseDoubleSpacedFormat; items = { DLG_LINE { type = EEikCtNumberEditor; prompt = "Number" ; id = EMyAppControlIdNumberEd ; control = NUMBER_EDITOR { min = 0; max = 999; }; }, DLG_LINE { type = EAknCtIntegerEdwin; prompt = "Integer edwin" ; id = EMyAppControlIdIntegerEd; itemflags = EEikDlgItemTakesEnterKey; control = AVKON_INTEGER_EDWIN { maxlength = 10; min = 0; max = 999; }; }, DLG_LINE { type = EEikCtFlPtEd; prompt = "Floating point" ; id = EMyAppControlIdFloatEd; itemflags = EEikDlgItemTakesEnterKey; control = FLPTED { maxlength = 10; min = 0; max = 999; }; }, DLG_LINE { type=EEikCtFxPtEd; prompt = "Fixed point" ; id = EMyAppControlIdFixEd; itemflags = EEikDlgItemTakesEnterKey; control = FIXPTED { min = 0; max = 99999; decimalplaces = 2; }; }, DLG_LINE { type = EEikCtDateEditor; prompt = "Date" ; id = EMyAppControlIdDateEd ; itemflags = EEikDlgItemTakesEnterKey; control = DATE_EDITOR { minDate = DATE { year = 1900; }; maxDate= DATE { year = 2100; }; flags = 0; }; }, DLG_LINE { type = EEikCtTimeEditor; prompt = "Time"; id = EMyAppControlIdTimeEd; itemflags = EEikDlgItemTakesEnterKey; control = TIME_EDITOR { minTime = TIME {}; maxTime = TIME { second = 59; minute = 59; hour = 23; }; flags = 0; }; }, DLG_LINE { type = EEikCtDurationEditor; prompt = "Duration"; id = EMyAppControlIdDurationEd; itemflags = EEikDlgItemTakesEnterKey; control = DURATION_EDITOR { minDuration = DURATION {}; maxDuration = DURATION { seconds = 3599; }; flags = 0; }; } }; } RESOURCE FORM r_my_form_3 { flags = EEikFormUseDoubleSpacedFormat; items = { DLG_LINE { type = EAknCtNumericSecretEditor; prompt = "Secret number"; id = EMyAppControlIdNumPwdEd; itemflags = EEikDlgItemTakesEnterKey; control = NUMSECRETED { num_code_chars = 4; }; }, DLG_LINE { type = EEikCtSecretEd; prompt = "Secret text"; id = EMyAppControlIdAlphaPwdEd; itemflags = EEikDlgItemTakesEnterKey; control = SECRETED { num_letters = 8; }; }, DLG_LINE { type = EAknCtIpFieldEditor; prompt = "IP address"; id = EMyAppControlIdIpAddrEd; itemflags = EEikDlgItemTakesEnterKey; control = IP_FIELD_EDITOR { min_field_values = IP_FIELD { first_field = 0; second_field = 0; third_field = 0; fourth_field = 0; }; max_field_values = IP_FIELD { first_field = 255; second_field = 255; third_field = 255; fourth_field = 255; }; flags = 0; }; }, DLG_LINE { type = EAknCtPopupField; prompt = "Popup field"; id = EMyAppControlIdPopupField; itemflags = EEikDlgItemTakesEnterKey; control = POPUP_FIELD { flags = EAknPopupFieldFlagAllowsUserDefinedEntry; width = 50; other = "Other"; empty = "No items"; invalid = "Invalid item"; }; }, DLG_LINE { type = EAknCtPopupFieldText; prompt = "Popup field text"; id = EMyAppControlIdPopupFieldText; itemflags = EEikDlgItemTakesEnterKey; control = POPUP_FIELD_TEXT { textarray = r_my_list_popup_items; popupfield = POPUP_FIELD {}; active = 0; }; }, DLG_LINE { type = EAknCtSlider; prompt = "Slider"; id = EMyAppControlIdSlider; itemflags = EEikDlgItemTakesEnterKey; control = SLIDER { layout = EAknFormSliderLayout2; minvalue = 0; maxvalue = 20; step = 2; valuetype = EAknSliderValueNone; minlabel = "few"; maxlabel = "many"; valuelabel = "Slider value"; }; } }; }
The following example code initializes sample data before invoking the form.
// Create example dynamic list for the popup field. CDesCArray* array = new (ELeave) CDesCArrayFlat( 8 ); CleanupStack::PushL( array ); array->AppendL( _L("January") ); array->AppendL( _L("February") ); array->AppendL( _L("March") ); array->AppendL( _L("April") ); array->AppendL( _L("May") ); array->AppendL( _L("June") ); CAknQueryValueTextArray* textArray = CAknQueryValueTextArray::NewLC(); textArray->SetArray( *array ); CAknQueryValueText* queryVal = CAknQueryValueText::NewLC(); queryVal->SetArrayL( textArray ); queryVal->SetCurrentValueIndex( 0 ); // Initialize example form data. TMyData myData; myData.iText = _L("This is a text."); myData.iGlobalText = _L("This is global text."); myData.iRichText = _L("This is rich text."); myData.iNumber = 5; myData.iInteger = 5; myData.iFloat = 1.234; myData.iFix = 12345; myData.iDate.HomeTime(); myData.iTime.HomeTime(); myData.iDuration = TTimeIntervalSeconds( 1000 ); myData.iNumPwd = _L("1234"); myData.iAlphaPwd = _L("passwd"); myData.iIpAddr = TInetAddr(); myData.iPopupVal = queryVal; myData.iPopupTextIndex = 2; myData.iSliderVal = 10; // Launch the dialog to view/edit data CAknForm* dlg = new ( ELeave ) CMyForm( myData ); CleanupStack::PushL( dlg ); dlg->ConstructL( 0 ); // default menu items only CleanupStack::Pop( dlg ); dlg->ExecuteLD( R_MY_DIALOG ); // myData now contains the edited values. CleanupStack::PopAndDestroy( queryVal ); CleanupStack::PopAndDestroy( textArray ); CleanupStack::PopAndDestroy( array );
PreLayoutDynInitL()
can be overridden to initialize form
controls.
void CMyForm::PreLayoutDynInitL() { CAknForm::PreLayoutDynInitL(); LoadFormDataL(); } void CMyForm::LoadFormDataL() { CEikEdwin* textEd = (CEikEdwin*)Control( EMyAppControlIdTextEd ); textEd->SetTextL( &iData.iText ); CEikGlobalTextEditor* globalTextEd = (CEikGlobalTextEditor*)Control( EMyAppControlIdGlobalTextEd ); globalTextEd->SetTextL( &iData.iGlobalText ); CEikRichTextEditor* richTextEd = (CEikRichTextEditor*)Control( EMyAppControlIdRichTextEd ); richTextEd->SetTextL( &iData.iRichText ); CEikNumberEditor* numberEd = (CEikNumberEditor*)Control( EMyAppControlIdNumberEd ); numberEd->SetNumber( iData.iNumber ); CAknIntegerEdwin* integerEd = (CAknIntegerEdwin*)Control( EMyAppControlIdIntegerEd ); integerEd->SetValueL( iData.iInteger ); CEikFloatingPointEditor* floatEd = (CEikFloatingPointEditor*)Control( EMyAppControlIdFloatEd ); floatEd->SetValueL( &iData.iFloat ); CEikFixedPointEditor* fixEd = (CEikFixedPointEditor*)Control( EMyAppControlIdFixEd ); fixEd->SetValueL( &iData.iFix ); CEikDateEditor* dateEd = (CEikDateEditor*)Control( EMyAppControlIdDateEd ); dateEd->SetDate( iData.iDate ); CEikTimeEditor* timeEd = (CEikTimeEditor*)Control( EMyAppControlIdTimeEd ); timeEd->SetTime( iData.iTime ); CEikDurationEditor* durationEd = (CEikDurationEditor*)Control( EMyAppControlIdDurationEd ); durationEd->SetDuration( iData.iDuration ); CAknNumericSecretEditor* numPwdEd = (CAknNumericSecretEditor*)Control( EMyAppControlIdNumPwdEd ); numPwdEd->SetText( iData.iNumPwd ); CEikSecretEditor* alphaPwdEd = (CEikSecretEditor*)Control( EMyAppControlIdAlphaPwdEd ); alphaPwdEd->SetText( iData.iAlphaPwd ); CAknIpFieldEditor* ipAddrEd = (CAknIpFieldEditor*)Control( EMyAppControlIdIpAddrEd ); ipAddrEd->SetAddress( iData.iIpAddr ); iData.iPopupVal->SetCurrentValueIndex( 0 ); CAknPopupField* popupField = (CAknPopupField*)Control( EMyAppControlIdPopupField ); popupField->SetQueryValueL( iData.iPopupVal ); CAknPopupFieldText* popupFieldText = (CAknPopupFieldText*)Control( EMyAppControlIdPopupFieldText ); popupFieldText->SetCurrentValueIndex( iData.iPopupTextIndex ); CAknSlider* slider = (CAknSlider*)Control( EMyAppControlIdSlider ); slider->SetValueL( iData.iSliderVal ); }
Pressing the Back softkey in the edit state causes calls to QuerySaveChangesL()
then SaveFormDataL()
or DoNotSaveFormDataL()
. The following example saves data from form
controls to the data structure.
TBool CMyForm::SaveFormDataL() { CEikEdwin* textEd = (CEikEdwin*)Control( EMyAppControlIdTextEd ); textEd->GetText( iData.iText ); CEikGlobalTextEditor* globalTextEd = (CEikGlobalTextEditor*)Control( EMyAppControlIdGlobalTextEd ); globalTextEd->GetText( iData.iGlobalText ); CEikRichTextEditor* richTextEd = (CEikRichTextEditor*)Control( EMyAppControlIdRichTextEd ); richTextEd->GetText( iData.iRichText ); CEikNumberEditor* numberEd = (CEikNumberEditor*)Control( EMyAppControlIdNumberEd ); iData.iNumber = numberEd->Number(); CAknIntegerEdwin* integerEd = (CAknIntegerEdwin*)Control( EMyAppControlIdIntegerEd ); (void)integerEd->GetTextAsInteger( iData.iInteger ); CEikFloatingPointEditor* floatEd = (CEikFloatingPointEditor*)Control( EMyAppControlIdFloatEd ); (void)floatEd->GetValueAsReal( iData.iFloat ); CEikFixedPointEditor* fixEd = (CEikFixedPointEditor*)Control( EMyAppControlIdFixEd ); (void)fixEd->GetValueAsInteger( iData.iFix ); CEikDateEditor* dateEd = (CEikDateEditor*)Control( EMyAppControlIdDateEd ); iData.iDate = dateEd->Date(); CEikTimeEditor* timeEd = (CEikTimeEditor*)Control( EMyAppControlIdTimeEd ); iData.iTime = timeEd->Time(); CEikDurationEditor* durationEd = (CEikDurationEditor*)Control( EMyAppControlIdDurationEd ); iData.iDuration = durationEd->Duration(); CAknNumericSecretEditor* numPwdEd = (CAknNumericSecretEditor*)Control( EMyAppControlIdNumPwdEd ); numPwdEd->GetText( iData.iNumPwd ); CEikSecretEditor* alphaPwdEd = (CEikSecretEditor*)Control( EMyAppControlIdAlphaPwdEd ); alphaPwdEd->GetText( iData.iAlphaPwd ); CAknIpFieldEditor* ipAddrEd = (CAknIpFieldEditor*)Control( EMyAppControlIdIpAddrEd ); iData.iIpAddr = ipAddrEd->Address(); iData.iPopupVal->SetCurrentValueIndex( 0 ); CAknPopupField* popupField = (CAknPopupField*)Control( EMyAppControlIdPopupField ); popupField->SetQueryValueL( iData.iPopupVal ); CAknPopupFieldText* popupFieldText = (CAknPopupFieldText*)Control( EMyAppControlIdPopupFieldText ); iData.iPopupTextIndex = popupFieldText->CurrentValueIndex(); CAknSlider* slider = (CAknSlider*)Control( EMyAppControlIdSlider ); iData.iSliderVal = slider->Value(); return ETrue; }
Forms can validate the entered data. SaveFormDataL()
should
return EFalse
if validation failed, this indicates that the
data has not been saved. In this case, the form remains in edit state.
DoNotSaveFormDataL()
is called if the user responds No
in QuerySaveChangesL()
. The form should restore the original
data.
void CMyForm::DoNotSaveFormDataL() { LoadFormDataL(); }
CAknForm
always uses menu pane R_AVKON_FORM_MENUPANE
.
This menu pane contains the following commands:
Command | Description |
---|---|
EAknFormCmdEdit |
Switches to edit mode (if allowed). |
EAknFormCmdAdd |
Adds field. Method AddFieldL() is called. Default
implementation is empty.
|
EAknFormCmdSave |
Saves and switches to view mode. SaveFormDataL() is
called. Default implementation is empty.
|
EAknFormCmdLabel |
Edits field label. Default implementation is provided. |
EAknFormCmdDelete |
Deletes field. DeleteCurrentItemL() is called. Default
implementation is empty.
|
EAknFormMaxDefault |
End marker for the enumeration. |
CAknForm
handles these commands and their associated menu
items.
DynInitMenuPaneL()
allows modifying the menu. The following
example appends the items of a custom menu pane to the form menu:
RESOURCE MENU_PANE r_my_extra_menu { items = { MENU_ITEM { command = EMyCommand; txt = "Dynamic menu item"; } }; }
void CMyForm::DynInitMenuPaneL( TInt aResourceId, CEikMenuPane* aMenuPane ) { CAknForm::DynInitMenuPaneL( aResourceId, aMenuPane ); if ( aResourceId == R_AVKON_FORM_MENUPANE ) { aMenuPane->AddMenuItemsL ( R_MY_EXTRA_MENU, EAknFormMaxDefault - 1, ETrue ); } }
The same effect can achieved by passing the ID of a MENU_BAR
resource
to CAknForm::ConstructL()
. Menu items from R_MY_MENUBAR
will
be appended to R_AVKON_FORM_MENUPANE
:
RESOURCE MENU_BAR r_my_menubar { titles= { MENU_TITLE { menu_pane = r_my_extra_menu; txt=""; } }; }
// Launch the dialog to view/edit data CAknForm* dlg = new ( ELeave ) CMyForm( myData ); CleanupStack::PushL( dlg ); dlg->ConstructL( R_MY_MENUBAR ); CleanupStack::Pop( dlg ); dlg->ExecuteLD( R_MY_DIALOG ); // myData now contains edited values.
ProcessCommandL()
can be overridden to handle custom commands.
Built-in form commands are handled by CAknForm
.
void CMyForm::ProcessCommandL( TInt aCommandId ) { // Form default commands. CAknForm::ProcessCommandL( aCommandId ); // Custom commands. switch ( aCommandId ) { case EMyCommand: User::InfoPrint( _L("my command") ); break; default: break; } }
In edit mode, fields can be added or deleted dynamically. CAknForm::AddItemL()
and CAknForm::DeleteCurrentItemL()
provide default implementation for handling the commands EAknFormCmdAdd
and EAknFormCmdDelete
,
respectively.
The following sample adds an editor control.
void CMyForm::AddItemL() { _LIT( caption, "Added text" ); TInt pageId = ActivePageId(); TInt id = iAddedItemId++; // All controls must have unique id. TInt type = EEikCtEdwin; TAny* unused=0; CEikEdwin* edwin = (CEikEdwin*)CreateLineByTypeL ( caption, pageId, id, type, unused ); edwin->ConstructL ( EEikEdwinNoHorizScrolling | EEikEdwinResizable, 10, 100, 1 ); Line( id )->ActivateL(); SetChangesPending( ETrue ); UpdatePageL( ETrue ); }
Note that all controls in the dialog must have a unique ID. The sample
code uses its iAddedItemId
member to ensure that IDs are
unique, but does not store the IDs of the dynamically created controls. Real-life
implementations need the IDs to access field data later.
enum TMyControlIds { EMyAppControlIdTextEd = 100, EMyAppControlIdGlobalTextEd, EMyAppControlIdRichTextEd, EMyAppControlIdNumberEd, EMyAppControlIdIntegerEd, EMyAppControlIdFloatEd, EMyAppControlIdFixEd, EMyAppControlIdDateEd, EMyAppControlIdTimeEd, EMyAppControlIdDurationEd, EMyAppControlIdNumPwdEd, EMyAppControlIdAlphaPwdEd, EMyAppControlIdIpAddrEd, EMyAppControlIdPopupField, EMyAppControlIdPopupFieldText, EMyAppControlIdSlider, EMyAppControlIdFirstAdded // Dynamically added items };
Adding fields dynamically is also useful if the form is used to manipulate
data which has a variable structure. In this case, the FORM structure can
be left empty in the resource definition, and PreLayoutDynInitL()
can
be used to add appropriate fields as necessary.
Custom controls can be added to dialogs by overriding CreateCustomControlL()
,
as described in document S60 3.1 Dialogs API Specification
.
In order to support laying out the custom control in forms, the method ConvertCustomControlTypeToBaseControlType()
must
be provided. This method determines the layout class of the custom control.
MEikDialogPageObserver::TFormControlTypes CMyForm::ConvertCustomControlTypeToBaseControlType( TInt aControlType ) const { if ( aControlType == EAknCtIpFieldEditor ) { // Help layout of custom control. return MEikDialogPageObserver::EMfneDerived; } return CAknForm::ConvertCustomControlTypeToBaseControlType( aControlType ); };
Form API uses standard Symbian OS error reporting mechanism and standard error codes.
Memory consumption of dialogs depends on the contained controls.
None.