Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3354993
  • 博文数量: 1450
  • 博客积分: 11163
  • 博客等级: 上将
  • 技术积分: 11101
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-25 14:40
文章分类

全部博文(1450)

文章存档

2017年(5)

2014年(2)

2013年(3)

2012年(35)

2011年(39)

2010年(88)

2009年(395)

2008年(382)

2007年(241)

2006年(246)

2005年(14)

分类: C/C++

2008-11-09 15:24:51

Series60提供了一个全面的对话框类和基类集合,可以使用这些类创建自定义对话框,以及开发窗体(form)、通知(note)、查询(query)和列表对话框(list dialog)等。

所 有对话框共有某些基本属性。首先,对话框都是拥有窗口的控件,所有对话框类最终都派生于CCoeControl。然后,由一个对话框框架管理对话框的行 为,包括布局、绘制以及用户与对话框在组件控件的交互。典型情况下,对于大多数任意复杂程度的对话框,都会在一个资源文件中完整定义,并在动态实例化之后 由对话框框架从资源文件装载此定义完成对话框的创建。对话框所有元素的布局和定位都是通常是自动的,当然也可以干预它。

Series60的对话框默认是模态和非等待的。模态/非模态无需多述;非等待对话框允许应用程序在后台继续处理,而等待对话框会阻止应用程序在该对话框关闭前执行任何进一步的处理。

CAknDialog是大部分Series60对话框的基类。关于对话框的使用,大体分为以下步骤:1.定义资源。2.编写对话框类。3.保存和验证对话框数据。4.动态地初始化标准对话框。5.构建和执行对话框。

下面分别叙述之:

1.定义资源

使用DIALOG定义资源,资源指定了对话框的布局,在资源中定义对话框应该包含的行数、使用的控件、对话框是否为模态以及使用的软键等。下面以一个简单的例子示范:

RESOURCE DIALOG r_simpledlg_dialog
{
flags=EEikDialogFlagNoDrag |
EEikDialogFlagNoTitleBar |
EEikDialogFlagFillAppClientRect |
EEikDialogFlagCbaButtons |
EEikDialogFlagModeless;
buttons=R_AVKON_SOFTKEYS_OPTIONS_BACK;
items=
{
DLG_LINE
{
id=ESimpleDlgCIdGameName;
type=EEikCtLabel;
control= LABEL
{
txt = GAME_NAME_TEXT;
};
}
};
}

flags说明了对话框的属性,其中的属性值可参考<uikon.hrh>

#define EEikDialogFlagWait
#define EEikDialogFlagNotifyEsc
#define EEikDialogFlagButtonsBelow
#define EEikDialogFlagButtonsRight
#define EEikDialogFlagNoUserExit
#define EEikDialogFlagModeless
#define EEikDialogFlagNoTitleBar
#define EEikDialogFlagAllKeysToButtons
#define EEikDialogFlagFillScreen
#define EEikDialogFlagNoDrag
#define EEikDialogFlagDensePacking
#define EEikDialogFlagNoBackup
#define EEikDialogFlagFillAppClientRect
#define EEikDialogFlagCbaButtons
#define EEikDialogFlagNoBorder
#define EEikDialogFlagNoShadow

其中,把标准对话框定义为等待对话框是一种良好的习惯。应该只在合理的时候(例如在主应用程序窗口中)才把标准对话框定义为非等待。

buttons指定了使用的软件,其中的取值可参考
#define R_AVKON_SOFTKEYS_EMPTY
#define R_AVKON_SOFTKEYS_EMPTY_WITH_IDS
#define R_AVKON_SOFTKEYS_OK_EMPTY
#define R_AVKON_SOFTKEYS_SELECT_CANCEL
#define R_AVKON_SOFTKEYS_OK_CANCEL
#define R_AVKON_SOFTKEYS_OK_DETAILS
#define R_AVKON_SOFTKEYS_CALL_CANCEL
#define R_AVKON_SOFTKEYS_OPTIONS_BACK
#define R_AVKON_SOFTKEYS_OPTIONS_DONE
#define R_AVKON_SOFTKEYS_OPTIONS_CANCEL
#define R_AVKON_SOFTKEYS_OPTIONS_EXIT
#define R_AVKON_SOFTKEYS_OK_BACK
#define R_AVKON_SOFTKEYS_CANCEL
#define R_AVKON_SOFTKEYS_BACK
#define R_AVKON_SOFTKEYS_CLOSE
#define R_AVKON_SOFTKEYS_DONE_BACK
#define R_AVKON_SOFTKEYS_DONE_CANCEL
#define R_AVKON_SOFTKEYS_SELECT_BACK
#define R_AVKON_SOFTKEYS_MARK_BACK
#define R_AVKON_SOFTKEYS_UNMARK_BACK
#define R_AVKON_SOFTKEYS_YES_NO
#define R_AVKON_SOFTKEYS_UNLOCK_EMPTY
#define R_AVKON_SOFTKEYS_SAVE_BACK
#define R_AVKON_SOFTKEYS_SHOW_CANCEL
#define R_AVKON_SOFTKEYS_SHOW_EXIT
#define R_AVKON_SOFTKEYS_ANSWER_EXIT
#define R_AVKON_SOFTKEYS_EXIT
#define R_AVKON_SOFTKEYS_READ_EXIT
#define R_AVKON_SOFTKEYS_LISTEN_EXIT
#define R_AVKON_SOFTKEYS_SEARCH_BACK
#define R_AVKON_SOFTKEYS_AGAIN_QUIT
#define R_AVKON_SOFTKEYS_QUIT
#define R_AVKON_SOFTKEYS_INSERT_BACK

最主要的是items组件,它定义了对话框包含的实际内容。需要为希望包含到对话框的每个控件分别定义一个DLG_LINE,在每个DLG_LINE中至少应该指定以下字段:

* id :在应用程序中使用该值引用此对话框行,必须在应用程序的.hrh文件中枚举它。
* type :此对话框行包含的控件类型(在avkon.hrh或uikon.hrh中定义)。
* control :在此对话框中使用的控件。

此 外,还可以选择在DLG_LINE资源中指定一个itemflags字段,使用该字段决定对话框行的行为。例如弹出字段文本控件可以使用 itemflags说明应该在“选择”键被按下时打开一个弹出窗口,例如 EEikDlgItemTakesEnterKey|EEikDlgItemOfferAllHotKeys。可以在uikon.hrh中找到 itemflags的值。最常用的可能当属EEikDlgItemSeparatorBefore标志,用于在对话框行之前插入一个水平“分隔符”行。

2. 编写对话框类

接下来需要编写一个可以构建和执行此对话框、初始化控件的数据、处理从控件接收到的数据并决定如何关闭对话框的类。

通常会提供一个用于执行对话框的静态方法,该方法包装了第一阶段构造函数和ExecuteLD() - 用于装载、显示和销毁对话框的函数。通常将该静态方法命名为RunDlgLD(),并使它传递ExecuteLD()返回的TBool。

下面示例之:

#include <akndialog.h> // CAknDialog
class CSimpleDlgPlayerNameDialog : public CAknDialog
{
public: // static construction and execution
static TBool RunDlgLD (TDes& aPlayerName);
protected: // from CAknDialog
TBool OkToExitL(TInt aButtonId);
protected: // from CEikDialog
void PreLayoutDynInitL();
private: // Constructor
CSimpleDlgPlayerNameDialog(TDes& aPlayerName) : iPlayerName(aPlayerName){};
private: // data
TDes& iPlayerName;
};

关于RunDlgLD()的实现:

TBool CSimpleDlgPlayerNameDialog::RunDlgLD (TDes& aPlayerName)
{
CSimpleDlgPlayerNameDialog* playerNameDialog = new (ELeave) CSimpleDlgPlayerNameDialog(aPlayerName);
return playerNameDialog->ExecuteLD(R_SIMPLEDLG_PLAYER_NAME_DIALOG);
}

因为对话框是模态和等待的,所以不需要使它成为成员数据,此对话框在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 ESimpleDlgCmdNewGame:
{
if (CSimpleDlgPlayerNameDialog::RunDlgLD (iPlayerName))
{
StartNewGameL();
}
break;
}
// ...
}

通过检查ExecuteLD()或RunDlgLD()的返回值,可以得知对话框是如何被关闭的。返回EFalse说明关闭对话框时按下的是“取消”、“后退”或“否”,其他情况下返回ETrue。

阅读(488) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~