1.构造与销毁
视图的构造是通过ConstructL()函数实现的,该函数以视图的资源ID作为参数调用基类的BaseConstructL()函数,通过资源文件创建视图。
视图的销毁在视图类的析构函数中实现。首先判断容器对象有没有被销毁,如果没有则需要从控件堆栈中弹出,然后销毁容器对象。代码如下:
CListView::~CListView()
{
if(iContainer!=NULL)
{
AppUi()->RemoveFromViewStack(*this,iContainer);
}
delete iContainer;
}
2.返回视图标识函数
应用程序的视图类需要重载CAknView::Id()函数,返回该视图的标识,实现代码如下:
TUid CListView::Id()const
{
return KViewId;
}
KViewId在CListView的头文件中定义,它是该视图的唯一标识,代码如下:
const TUid KViewId={1};
3.视图的激活与反激活
DoActivateL()函数和DoDeactivate()函数分别负责处理视图的激活和反激活事件。
视图创建后在显示视图之前应用程序框架调用它的DoActiveL()函数,该函数的主要功能是创建视图的容器对象,并把它压入控件堆栈中以响应按键事件,代码如下:
void CListView::DoActivateL(const TVwsViewId& /*aPrevViewId*/,TUid /*aCustomMessageId*/,
const TDesC8& aCustomMessage*/)
{
if(!iContainer)
{
iContainer= new(Eleave)CListViewContainer;
iContainer->SetMopParent(this);
iContainer->ConstructL(ClientRect());
AppUi()->AddToStackL(*this,iContainer);
}
}
注意:开发人员要保证DoActivateL()函数尽快执行完毕,尤其注意不要在这个函数中加入等待用户响应的代码,否则可能会产生“ViewSrv11”严重错误。
当程序切换到其他视图时,应用程序框架会调用视图类的DoDeactivate()函数,该函数的主要功能是将容器对象从控件堆栈弹出并销毁。
void CListView::DoDeactivate()
{
if(iContainer!=NULL)
{
AppUi()->RemoveFromViewStack(*this,iContainer);
}
delete iContainer;
iContainer=NULL;
}
使用delete语句销毁容器对象时,只是释放了该对象的内存空间,并没有将该对象的指针置为NULL。如果之后的程序代码仍会使用该指针,发现该指针不为空,会认为这个对象仍存在,从而导致错误访问。
4.处理用户命令
HandleCommandL()函数负责处理用户的命令,主要是菜单命令。系统首先调用视图类的HandleCommandL()函数,该函数只有一个TInt类型的参数,代表菜单命令ID。通过判断这个命令ID,如果是视图特有的命令,则在视图类中处理,如果是应用程序范围内的命令,则转发给AppUi类的HandleCommandL()函数处理。代码实现如下:
#include "MymultiView.hrh" //需要包含的头文件
void CListView::HandleCommandL(TInt aCommand)
{
switch ( aCommand )
{
case EMyMultiViewCmdList: //EMyMultiViewCmdList在mymultiview.rss和mymultiview.hrh中定义
{
iEikonEnv->InfoMsg( _L("Command from Listview") );
break;
}
case EAknSoftkeyBack:
{
AppUi()->HandleCommandL(EEikCmdExit);
break;
}
default:
{
AppUi()->HandleCommandL( aCommand );
break;
}
}
}
{
switch ( aCommand )
{
case EMyMultiViewCmdList: //EMyMultiViewCmdList在mymultiview.rss和mymultiview.hrh中定义
{
iEikonEnv->InfoMsg( _L("Command from Listview") );
break;
}
case EAknSoftkeyBack:
{
AppUi()->HandleCommandL(EEikCmdExit);
break;
}
default:
{
AppUi()->HandleCommandL( aCommand );
break;
}
}
}
这里的EMyMultiViewCmdList是视图类特有的命令,所以在CListView类中处理。而EAknSoftkeyBack命令式应用程序通用的菜单命令,因此交给AppUi类处理。这里的其他菜单命令也交给AppUi类处理,好处是通用的菜单项发生变化时,无须修改各个视图类的实现代码。
AppUi类的HandleCommandL()函数负责处理通用菜单命令。CMyMultiViewAppUi类的HandleCommandL()函数实现如下:
void CMyMultiViewAppUi::HandleCommandL(TInt aCommand)
{
switch ( aCommand )
{
case EEikCmdExit:
{
Exit();
break;
}
case EMyMultiViewCmdAppTest:
{
iEikonEnv->InfoMsg(_L("test"));
break;
}
// TOD Add Your command handling code here
{
switch ( aCommand )
{
case EEikCmdExit:
{
Exit();
break;
}
case EMyMultiViewCmdAppTest:
{
iEikonEnv->InfoMsg(_L("test"));
break;
}
// TOD Add Your command handling code here
default:
break;
}
}
break;
}
}
这里处理了两个通用命令:EEikCmdExit和EMyMultiViewCmdAppTest。对于edit视图中的代码和list视图类似。
在模拟器环境下,CEikonEnv::InfoMsg()函数可以在屏幕右上角显示一个信息窗口,该窗口持续一段时间自动消失。在AppUi类、视图类、CCoeControl的派生类中都可以使用该函数,例如:
iEikonEnv->InfoMsg(_L("some text"));
结论:在视图应用程序中,用户菜单命令由视图类的HandleCommandL()函数处理。一般要先判断菜单命令是否需要在视图类中处理,如果不是则可以调用AppUi类的HandleCommandL()函数处理该命令。
5.响应客户区变化
客户区变化时,应用程序框架会调用视图类的HandleClientRectChange()函数,在该函数中重新设置视图中各控件的区域。由于本例中的视图类只包含一个容器对象,因此代码:
void CListView::HandleClientRectChange()
{
if ( iContainer )
{
iContainer->SetRect( ClientRect() );
}
}
{
if ( iContainer )
{
iContainer->SetRect( ClientRect() );
}
}