原文:http://www.cppblog.com/gtwdaizi/articles/35962.html
1、非阻塞提示框
symbian定义了几个提示类,分别是:
confirm类:CAknConfirmationNote
info类: CAknInformationNote
warning类:CAknWarningNote
error类:CAknErrorNote
头文件:aknnotewrappers.h
lib: avkon.lib eikcdlg.lib eikctl.lib
Code:
TBuf<32> buf;
buf.Copy(_L("info note"));
CAknInformationNote* iInfoNote = new (ELeave) CAknInformationNote;
iInfoNote->ExecuteLD(buf);
2、阻塞提示框
void CEikonEnv::AlertWin(const TDesC& aMsg);
void CEikonEnv::AlertWin(const TDesC& aMsg1,const TDesC& aMsg2);
static void CEikonEnv::InfoWinL(const TDesC& aFirstLine,const TDesC& aSecondLine);
AlertWin为CEikonEnv类的非静态成员函数,InfoWinL为CEikonEnv类的静态成员函数。
AlertWin只能在ui、view和container中使用,使用方法如下:
Code:
iEikonEnv->AlertWin(_L("text"));
InfoWinL可以在任意类中使用,使用方法如下:
Code:
CEikonEnv::Static()->InfoWinL(_L("note:"), _L("text"));
为方便使用,常定义宏来使用这类提示框,如:
Code:
#define DEBUG_DIALOG(x) iEikonEnv->AlertWin(##x);
#define DEBUG_DIALOG1(x) CEikonEnv::Static()->InfoWinL(_L("note:"), ##x);
#define DEBUG_DIALOG2(x,y) CEikonEnv::Static()->InfoWinL(##x, ##y);
可以这么使用:
TBuf<32> buf;
buf.Copy(_L("test"));
DEBUG_DIALOG(buf);
DEBUG_DIALOG1(buf);
DEBUG_DIALOG2(buf,_L("text"));
此类提示框阻塞线程,只有用户按键退出提示框后,后面的程序才能接着运行。
3、进度条对话框
进度条对话框类为:
CAknProgressDialog
头文件:aknprogressdialog.h
lib:avkon.lib eikcdlg.lib eikctl.lib
Code:
//初始化进度条
CAknProgressDialog* iProgressDialog;
CEikProgressInfo* iProgressInfo;
iProgressDialog = new ( ELeave ) CAknProgressDialog( reinterpret_cast
<CEikDialog**>
( &iProgressDialog ) );
iProgressDialog->SetCallback( this );
iProgressDialog->PrepareLC( R_RESOURCE_PROGRESS_NOTE ); //从资源文件构造对话框,资源见下面的定义
iProgressInfo = iProgressDialog->GetProgressInfoL();
iProgressInfo->SetFinalValue( aMaxValue ); //设置进度条的最大值(结束值)
iProgressDialog->RunLD();
//更新进度条
iProgressInfo->IncrementAndDraw( aStep );
//结束进度条
iProgressDialog->ProcessFinishedL();
delete iProgressDialog;
RESOURCE DIALOG R_RESOURCE_PROGRESS_NOTE //进度条对话框资源
{
flags = EAknProgressNoteFlags;
buttons = R_AVKON_SOFTKEYS_CANCEL;
items =
{
DLG_LINE
{
type = EAknCtNote;
id = EMagicBoxCtrlIdProgressNote;
control = AVKON_NOTE
{
layout = EProgressLayout;
singular_label = "对话框中显示的文字";
plural_label = "download";
imagefile = AVKON_BMPFILE_NAME; //第二版中 图标文件为 #define AVKON_BMPFILE_NAME "z://system//data//avkon.mbm"
imageid = EMbmAvkonQgn_note_sml; //这两项可更改显示不同图标
imagemask = EMbmAvkonQgn_note_sml_mask;
};
}
};
}
注 意:In Series 60 3rd edition, avkon.mbm was replaced by avkon2.mbm and moved to a different location (and the SDK forgot to mention this and still provides erroneous location).
Old entry:
imagefile = "z://system/data/avkon.mbm";
New entry:
imagefile = "z://resource/apps/avkon2.mbm";
4、等待对话框
等待对话框要用到的类:CAknGlobalNote
头文件:aknglobalnote.h
lib:aknnotify.lib eiksrv.lib
Code:
//显示等待对话框
CAknGlobalNote* globalNote = CAknGlobalNote::NewL();
CleanupStack::PushL( globalNote );
TInt iWaitNoteId = globalNote->ShowNoteL( EAknGlobalWaitNote, _L("对话框中显示的文字") );
CleanupStack::PopAndDestroy();
//结束等待对话框
CAknGlobalNote * note = CAknGlobalNote::NewL();
CleanupStack::PushL( note );
note->CancelNoteL( iWaitNoteId );
CleanupStack::PopAndDestroy();
注意:
CAknGlobalNote类除了显示等待对话框外还可显示多种类型的全局对话框,具体类型可通过ShowNoteL的第一个参数指定,可能的类型如下:
Code:
enum TAknGlobalNoteType
{
EAknGlobalInformationNote = 1,
EAknGlobalWarningNote,
EAknGlobalConfirmationNote,
EAknGlobalErrorNote,
EAknGlobalChargingNote,
EAknGlobalWaitNote,
EAknGlobalPermanentNote,
EAknGlobalNotChargingNote,
EAknGlobalBatteryFullNote,
EAknGlobalBatteryLowNote,
EAknGlobalRechargeBatteryNote,
EAknCancelGlobalNote,
EAknGlobalTextNote
};
5、询问对话框
询问对话框用到的类:CAknQueryDialog
头文件:AknQueryDialog.h
lib:avkon.lib
Code:
CAknQueryDialog* dlg;
dlg = CAknQueryDialog::NewL( CAknQueryDialog::ENoTone );
dlg->PrepareLC( R_RESOURCE_QUERY_DIALOG ); //从资源文件构造对话框,资源见下面的定义
TInt ret = dlg->RunLD(); //若用户选择“是”,返回非0,选择“否”,则返回0
RESOURCE DIALOG R_RESOURCE_QUERY_DIALOG //询问对话框资源
{
flags = EGeneralQueryFlags;
buttons = R_AVKON_SOFTKEYS_YES_NO; //CBA显示“是”和“否”两个按钮
items =
{
DLG_LINE
{
type = EAknCtQuery;
id = EGeneralQuery;
control = AVKON_CONFIRMATION_QUERY //表示这是confirm询问对话框,用户选择“是”或“否”
{
layout = EConfirmationQueryLayout;
label = "对话框中显示的文字";
};
}
};
}
此类对话框可以有声音提示,由NewL的const TTone& aTone参数指定,可能的值如下:
Code:
enum TTone {
/// No tone is played
ENoTone = 0,
/// A confirmation tone is played
EConfirmationTone = EAvkonSIDConfirmationTone,
/// A warning tone is played
EWarningTone = EAvkonSIDWarningTone,
/// An error tone is played
EErrorTone = EAvkonSIDErrorTone
};
通过定义不同的询问对话框资源,可实现不同的询问对话框,如让用户输入文字的询问对话框资源定义如下:
Code:
RESOURCE DIALOG R_RESOURCE_DATA_QUERY
{
flags = EGeneralQueryFlags;
buttons = R_AVKON_SOFTKEYS_OK_CANCEL; //CBA按钮显示“确定”和“取消”
items =
{
DLG_LINE
{
type = EAknCtQuery;
id = EGeneralQuery;
control = AVKON_DATA_QUERY //表示这是data询问对话框,需要用户输入内容
{
layout = EDataLayout;
label = "提示内容";
control = EDWIN
{
flags = EEikEdwinNoHorizScrolling | EEikEdwinResizable;
width = 30;
lines = 2;
maxlength = 159;
};
};
}
};
}
Code:
TBuf<128> msg;
CAknTextQueryDialog* dlg = new (ELeave) CAknTextQueryDialog(msg,CAknQueryDialog::ENoTone);
TInt ret = dlg->ExecuteLD(R_RESOURCE_DATA_QUERY);
用户输入内容后按“确定”,内容就存储到msg中,函数返回非0;按“取消”,函数返回0。
这里用到的类是CAknQueryDialog的子类CAknTextQueryDialog。
CAknQueryDialog的子类有:
Code:
CAknFloatingPointQueryDialog //This class should be used when user is reguest to enter a flotaing point number
CAknFixedPointQueryDialog //...
CAknDurationQueryDialog //This class should be used when user is reguest to enter duration
CAknIpAddressQueryDialog //This class should be used when user is reguest to enter IP address,@since 2.1
CAknMultiLineDataQueryDialog //Query Dialog with data input on more than one line (2 lines at the moment)
Create using NewL methods and passing parameters as appropriate.
Attention: When deriving from this class, you must call SetDataL during
second phase construction.
CAknMultiLineIpQueryDialog //...
CAknNumberQueryDialog //This class should be used when user is reguest to enter number
CAknTextQueryDialog //This class should be used when user is reguest to enter plain text, secret text, phonenumber or PIN-code
CAknTimeQueryDialog //This class should be used when user is reguest to enter time or date
使用不同的类,资源文件会有所不同。
另外,在资源中定义EDWIN时,可指定输入发,如:
Code:
control = EDWIN
{
flags = EEikEdwinNoHorizScrolling | EEikEdwinResizable;
width = 11;
lines = 1;
maxlength = 11;
avkon_flags = EAknEditorFlagFixedCase |
EAknEditorFlagNoT9 | EAknEditorFlagSupressShiftMenu; //EAknEditorFlagSupressShiftMenu屏蔽切换输入法键
allowed_input_modes = EAknEditorNumericInputMode;
default_input_mode = EAknEditorNumericInputMode;
numeric_keymap = EAknEditorPlainNumberModeKeymap;
};
以上写法表示默认输入法为数字,并且屏蔽了输入法切换键,即不能通过输入法切换键来切换输入法。
6、编辑框
编辑框使用的类:CEikGlobalTextEditor
头文件:eikgted.h
Code:
CEikGlobalTextEditor* iGKeyEd;
TBuf<128> iKeyText;
TResourceReader reader;
iCoeEnv->CreateResourceReaderLC( reader, R_RESOURCE_EDITOR ); //从资源文件构造编辑框,资源见下面的定义
iGKeyEd = new ( ELeave ) CEikGlobalTextEditor;
iGKeyEd->SetContainerWindowL( *this );
iGKeyEd->ConstructFromResourceL( reader );
CleanupStack::PopAndDestroy(); // Resource reader
//设置编辑框的初始文本和位置,编辑框大小在资源中定义
TBuf<32> buf;
buf.Copy(_L("demo"));
iGKeyEd->SetTextL(&buf);
iGKeyEd->SetExtent( TPoint(5,2), iGKeyEd->MinimumSize() );
iGKeyEd->SetFocus(ETrue);
// iGKeyEd->SetReadOnly(ETrue); //设置编辑框为只读
//使文字居中
CParaFormat paraFormat;
TParaFormatMask paraFormatMask;
paraFormatMask.SetAttrib( EAttAlignment ); // set mask
paraFormat.iHorizontalAlignment = CParaFormat::ECenterAlign;
iGKeyEd->ApplyParaFormatL( ¶Format, paraFormatMask );
iGKeyEd->GetText(iKeyText); //获取编辑框中的内容,保存到iKeyText中
RESOURCE GTXTED R_RESOURCE_EDITOR //编辑框资源
{
flags = EAknEditorFlagDefault;
width = 53;
height = 16;
numlines = 1;
textlimit= 1;
fontcontrolflags = EGulFontControlAll;
fontnameflags = EGulNoSymbolFonts;
//这里也可设置输入法
// avkon_flags = EAknEditorFlagFixedCase |
EAknEditorFlagNoT9 | EAknEditorFlagSupressShiftMenu; //EAknEditorFlagSupressShiftMenu屏蔽切换输入法键
// allowed_input_modes = EAknEditorNumericInputMode;
// default_input_mode = EAknEditorNumericInputMode;
// numeric_keymap = EAknEditorPlainNumberModeKeymap;
}
注意,要使编辑框正常显示,记得更改container的CountComponentControls 和ComponentControl函数,正确处理控件数目和编辑框指针。另外,要使编辑框能正常接收按键事件,要显示调用编辑框的 OfferKeyEventL函数,如下:
Code:
TKeyResponse CMobileGuardSetKeyContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
{
return iGKeyEd->OfferKeyEventL( aKeyEvent, aType );
}
自定义对话框:
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指定了使用的软件,其中的取值可参考<avkon.rsg>
#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
#include <aknquerydialog.h>
class CSimpleDlgPlayerNameDialog : public CAknTextQueryDialog
{
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()
{
CAknQueryControl* control = QueryControl();
//动态设置标题
control->SetPromptL(iPrompt->Des());
//动态设置初始的内容
control->SetTextL(iDefault->Des());
{
CEikEdwin*edwin = static_cast<CEikEdwin*>(control->ControlByLayoutOrNull(EDataLayout));
//设置允许的输入法还可以设置默认的输入法
edwin->SetAknEditorAllowedInputModes(EAknEditorTextCase);
}
MakeLeftSoftkeyVisible( ETrue );
}
如果需要,可以通过重写另外一个方法PostLayoutDynInitL(),更改对话框中控件的布局和大小,或是在显示对话框之前启动一个定时器。
5. 构建和执行对话框
RunDlgLD()方法封装了对话框的构建和执行。
switch (aCommand)
{
case ESimpleDlgCmdNewGame:
{
if (CSimpleDlgPlayerNameDialog::RunDlgLD (iPlayerName))
{
StartNewGameL();
}
break;
}
// ...
}
通过检查ExecuteLD()或RunDlgLD()的返回值,可以得知对话框是如何被关闭的。返回EFalse说明关闭对话框时按下的是“取消”、“后退”或“否”,其他情况下返回ETrue。
5. 根据情况显示对话框:
还可以动态的根据不同的情况创建不同的对话框。
TInt resouceID=R_DIALOG_TEXT_EDIT_QUERY;
switch(iType)
{
case INPUT_TYPE_ANY:
{
resouceID = R_DIALOG_TEXT_EDIT_QUERY;
}
break;
case INPUT_TYPE_NUM:
{
resouceID = R_DIALOG_FLOAT_NUM_EDIT_QUERY;
}
break;
case INPUT_TYPE_ABC:
{
resouceID = R_DIALOG_TEXT_EDIT_QUERY;
}
break;
case INPUT_TYPE_PASSWORD:
{
resouceID = R_DIALOG_SECRET_EDIT_QUERY;
}
break;
case INPUT_TYPE_PHONENUMBER:
{
resouceID = R_DIALOG_PHONE_NUM_EDIT_QUERY;
}
break;
case INPUT_TYPE_PIN:
{
resouceID = R_DIALOG_PIN_EDIT_QUERY;
}
break;
}
return ExecuteLD(resouceID);