收藏
Series60提供了一个全面的对话框类和基类集合,可以使用这些类创建自定义对话框,以及开发窗体(form)、通知(note)、查询(query)和列表对话框(list dialog)等。
所有对话框共有某些基本属性。首先,对话框都是拥有窗口的控件,所有对话框类最终都派生于CCoeControl。然后,由一个对话框框架管理对话框的行为,包括布局、绘制以及用户与对话框在组件控件的交互。典型情况下,对于大多数任意复杂程度的对话框,都会在一个资源文件中完整定义,并在动态实例化之后由对话框框架从资源文件装载此定义完成对话框的创建。对话框所有元素的布局和定位都是通常是自动的,当然也可以干预它。
Series60的对话框默认是模态和非等待的。模态/非模态无需多述;非等待对话框允许应用程序在后台继续处理,而等待对话框会阻止应用程序在该对话框关闭前执行任何进一步的处理。
一、继承基类对话框CAknDialog
CAknDialog是大部分Series60对话框的基类。关于对话框的使用,大体分为以下步骤:1.定义资源。2.编写对话框类。3.保存和验证对话框数据。4.动态地初始化标准对话框。5.构建和执行对话框。
下面分别叙述之:
1.定义资源
使用DIALOG定义资源,资源指定了对话框的布局,在资源中定义对话框应该包含的行数、使用的控件、对话框是否为模态以及使用的软键等。下面以一个简单的例子示范:
RESOURCE DIALOG r_simpledlg_player_name_dialog
{
flags=EEikDialogFlagNoDrag |
EEikDialogFlagCbaButtons |
EEikDialogFlagWait;
buttons=R_AVKON_SOFTKEYS_OK_CANCEL;
items=
{
DLG_LINE
{
id=ESimpleDlgCIdPlayerName;
type=EEikCtLabel;
control= LABEL
{
};
},
DLG_LINE
{
id=ESimpleDlgCIdPlayerNameEditor;
type=EEikCtEdwin;
control= EDWIN
{
maxlength = KMaxPlayerNameLength;
};
}
};
}
flags说明了对话框的属性,其中的属性值可参考<uikon.hrh>
buttons指定了使用的软键。
最主要的是items组件,它定义了对话框包含的实际内容。需要为希望包含到对话框的每个控件分别定义一个DLG_LINE,在每个DLG_LINE中至少应该指定以下字段:
* id :在应用程序中使用该值引用此对话框行,必须在应用程序的.hrh文件中枚举它。
* type :此对话框行包含的控件类型(在avkon.hrh或uikon.hrh中定义)。
* control :在此对话框中使用的控件。
此外,还可以选择在DLG_LINE资源中指定一个itemflags字段,使用该字段决定对话框行的行为。例如弹出字段文本控件可以使用itemflags说明应该在“选择”键被按下时打开一个弹出窗口,例如EEikDlgItemTakesEnterKey。可以在uikon.hrh中找到itemflags的值。最常用的可能当属EEikDlgItemSeparatorBefore标志,用于在对话框行之前插入一个水平“分隔符”行。
2. 编写对话框类
接下来需要编写一个可以构建和执行此对话框、初始化控件的数据、处理从控件接收到的数据并决定如何关闭对话框的类。
通常会提供一个用于执行对话框的静态方法,该方法包装了第一阶段构造函数和ExecuteLD() - 用于装载、显示和销毁对话框的函数。通常将该静态方法命名为RunDlgLD(),并使它传递ExecuteLD()返回的TBool。
下面示例之:
#include <akndialog.h> // CAknDialog
#include <aknquerydialog.h>
#include <aknquerycontrol.h>
class CSimpleDlgPlayerNameDialog : public CAknDialog //public CAknTextQueryDialog
{
public:
// static construction and execution
static TBool RunDlgLD(TDes& aPlayerName);
protected:
// from CAknDialog
TBool OkToExitL(TInt aButtonId);
protected:
void PreLayoutDynInitL();
private:
// Constructor
CSimpleDlgPlayerNameDialog(TDes& aPlayerName) ://CAknTextQueryDialog(aPlayerName),
iPlayerName(aPlayerName)
{
}
;
private:
// data
TDes& iPlayerName;
};
关于RunDlgLD()的实现:
TBool CSimpleDlgPlayerNameDialog::RunDlgLD (TDes& aPlayerName)
{
CEikLabel* label = static_cast<CEikLabel*>(ControlOrNull(ESimpleDlgCIdPlayerName));
if (label)
{
HBufC* labelText = StringLoader::LoadLC(R_ENTER_NAME_TEXT);
label->SetTextL(*labelText);
CleanupStack::PopAndDestroy(labelText);
}
}
因为对话框是模态和等待的,所以不需要使它成为成员数据,此对话框在ExecuteLD()的最后会删除自己。
那么为什么在new之后没有将其压入清除栈呢?因为ExecuteLD()拥有改对话框的所有权,该方法包装了对其他两个方法的调用:PrepareLC()和RunLD()。 PrepareLC()会把对话框的指针放入清除栈,然后完成对话框的创建。RunLD()会显示该对话框,然后把它从清除栈中弹出。但如果在调用ExecuteLD()之前需要调用任意可能导致异常退出的代码,则应该将其放入清除栈,并在调用ExecuteLD()前把它弹出。
但,如果对话框为非等待的,则会直接从ExecuteLD()返回而不被删除。
3. 保存和验证对话框数据
为了使对话框能够更新应用程序的数据,需要为它提供对这些数据的引用。对数据的验证和更新通常发生在OkToExitL()方法中进行,除“取消”外,按下任意软键时,框架都会调用此函数(通过设定对话框的flags,使之包括EEikDialogFlagNotifyEsc,可以强制要求框架在“取消”被按下时也调用OkToExitL())。如果允许对话框退出,则OkToExitL()必须返回ETrue,如果不允许退出,则返回EFalse。下面示例之:
TBool CSimpleDlgPlayerNameDialog::OkToExitL(TInt aButtonId)
{
if (aButtonId == EAknSoftkeyOk)
{
CEikEdwin* editor = static_cast<CEikEdwin*>(ControlOrNull(ESimpleDlgCIdPlayerNameEditor));
if (editor)
{
editor->GetText(iPlayerName);
}
}
return ETrue;
}
通过调用CEikDialog::ControlOrNull()并传入对话框行的ID,可以获取特定控件的句柄,如果ID有效,则返回一个CCoeControl的指针,后则返回NULL。如果ID无效需要退出,可使用CEikDialog::Control(),如果ID无效,该方法会出错。
4. 动态地初始化标准对话框
动态地设置对话框中的项是在PreLayoutDynInitL()方法中执行。对话框框架会在对话框执行前调用该方法。
void CSimpleDlgPlayerNameDialog::PreLayoutDynInitL()
{
CEikLabel* label = static_cast<CEikLabel*>(ControlOrNull(ESimpleDlgCIdPlayerName));
if (label)
{
HBufC* labelText = StringLoader::LoadLC(R_ENTER_NAME_TEXT);
label->SetTextL(*labelText);
CleanupStack::PopAndDestroy(labelText);
}
}
如果需要,可以通过重写另外一个方法PostLayoutDynInitL(),更改对话框中控件的布局和大小,或是在显示对话框之前启动一个定时器。
5. 构建和执行对话框
RunDlgLD()方法封装了对话框的构建和执行。
switch (aCommand)
{
case ECmdSimpleDlg:
CSimpleDlgPlayerNameDialog::RunDlgLD(iPlayerName) ;
break;break;
}
// ...
}
通过检查ExecuteLD()或RunDlgLD()的返回值,可以得知对话框是如何被关闭的。返回EFalse说明关闭对话框时按下的是“取消”、“后退”或“否”,其他情况下返回ETrue。
二、继承数据查询对话框CAknTextQueryDialog
继承数据查询对话框CAknTextQueryDialog的步骤和继承基类对话框CAknDialog大体相似,也是需要1.定义资源。2.编写对话框类。3.保存和验证对话框数据。4.动态地初始化标准对话框。5.构建和执行对话框。
1、定义资源
RESOURCE DIALOG r_question_data_query_dialog
{
flags = EGeneralQueryFlags;
buttons = R_AVKON_SOFTKEYS_OK_CANCEL;
items =
{
DLG_LINE
{
type = EAknCtQuery;
id = EGeneralQuery;
control = AVKON_DATA_QUERY
{
layout = EDataLayout;
label = question_text;
control = EDWIN
{
flags = EEikEdwinNoHorizScrolling | EEikEdwinResizable;
default_input_mode = EAknEditorTextInputMode;
maxlength = KMaxQuestionLength;
};
};
}
};
}
定义的资源和CAknTextQueryDialog的定义格式相同,这里不做详细解释。
2、编写对话框类
#include <aknquerydialog.h>
/**
* CTextDialog
*
*/
class CTextDialog : public CAknTextQueryDialog
{
public:
//构造函数
CTextDialog(TDes& aDataText):CAknTextQueryDialog(aDataText)
{
}
;
static CTextDialog* NewL(TDes& aDataText);
private:
protected:
void PreLayoutDynInitL();
};
类CTextDialog的构造函数需要初始化基类CAknTextQueryDialog,否则会出现cannot construct CTextDialog's base class 'CAknTextQueryDialog'的错误,如何初始化基类的构造函数,可以上网去查询C++的关于如何初始化基类构造函数,这里不做详细描述。
3、保存和验证对话框数据
该部分需要重写OkToExitL函数,这里直接由基类OkToExitL保存和验证对话框数据。
4、动态地初始化标准对话框
void CTextDialog::PreLayoutDynInitL()
{
CAknQueryControl* control = QueryControl();
if (control)
control->SetTextL(iDataText); //显示文本框初始内容
//默认情况下,当文本框内容为空时,对话框左键不显示,使用MakeLeftSoftkeyVisible函数将显示左键
MakeLeftSoftkeyVisible(ETrue);
}
5、构建和执行对话框
switch (aCommand)
{ // code to dispatch to the AknView's menu and CBA commands is generated here
case ECmdQeuryTextDlg:
CTextDialog *dialog = new (ELeave)CTextDialog(iProblem);
if (dialog->ExecuteLD(R_QUESTION_DATA_QUERY_DIALOG) )
{
}
break;
//...
}
}
默认情况下,CAknTextQueryDialog的“确定”或“OK”按钮在输入对话框内容为空时会隐藏,CTextDialog对话框主要是解决能够在对话框的文本框里输入空字符串。
总结,第一部分内容参考了《Series 60应用程序开发》中关于对话框章节的内容。第二部分是项目中需要自己写的,源代码请到CSDN:http://download.csdn.net/source/832037地址下载.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/doubleblue/archive/2008/12/03/3435282.aspx