Each view controller acts like a small UI controller.
The call on the first phase constructor of the view controller occurs in the UI controller.
The methods you need to implement in your CAknView
-derived
class are as follows:
C++ default constructor, which cannot contain any code that might leave. A common implementation is:
CMyViewAppView::CMyViewAppView() { }
The class declaration for this constructor in the class header file needs to be public to support the construction method required.
two-phase constructor, a common implementation is:
CMyViewAppView* CMyViewAppView::NewL( const TRect& aRect ) { CMyViewAppView* self = CMyViewAppView::NewLC( aRect ); CleanupStack::Pop( self ); return self; } CMyViewAppView* CMyViewAppView::NewLC( const TRect& aRect ) { CMyViewAppView* self = new ( ELeave ) CMyViewAppView; CleanupStack::PushL( self ); self->ConstructL( aRect ); return self; }
The declarations for CMyViewAppView::NewL()
and CMyViewAppView::NewLC()
in
the class header file needs to be public to support the construction method
required.
In this approach, CMyViewAppView::NewL()
is called
from the UI controller. It creates a view object by calling CMyViewAppView::NewLC()
. CMyViewAppView::NewLC()
calls new (ELeave
) on the C++ default constructor CMyViewAppView
to
create the object (and leave if it cannot), pushes a pointer to the clean-up stack in case the second phase construction method
leaves, and then calls the second phase construction method of the object.
When it returns to CMyViewAppView::NewL()
, the pointer
pushed to the cleanup stack is removed.
Symbian 2nd phase constructor with code that might leave. A common implementation is:
void CMyViewAppView::ConstructL() { // construct r_name32 resources BaseConstructL(r_name32 ); }
CMyViewAppView::ConstructL()
is a public class
providing the second phase construction that accepts the rectangle the view
is drawn to.
CAknView::BaseConstructL()
initializes this view
with standard values. It accepts the symbolic ID name of a resource from the
resource file.
a method for returning the UID for the view. A common implementation is:
TUid CMyViewAppView::Id() const { return KViewId; }
CMyViewAppView::Id()
is the override of CAknView::ID()
to
return the UID of the view
KViewId
is defined somewhere in a header file,
and is unique to this application
If you wish to support scalability in
your application, then you need to implement CEikAppUi::HandleResourceChangeL()
in
the UI controller,
and then a HandleClientRectChange
method in the view
controller.
A common implementation is as follows:
void CMyViewAppView::HandleClientRectChange() { if ( iContainer ) { iContainer->SetRect( ClientRect() ); } }
, where
CMyViewAppView::HandleClientRectChange()
calls CCoeControl::SetRect(aRect)
to
set the window size according to the requirements of the mobile device.
In order for a view to be displayed, it needs to be activated by CAknView::DoActivateL()
.
The override of this method in the view controller must create a CCoeControl
-derived
view to display visual content to mobile device users. The DoActivateL()
call
must be prepared to handle the case where it is called while the view is already
active.
If the view is not published for external use, or does not handle message parameters, a simple check and return if the view is already active is sufficient.
A common implementation is as follows:
void CMyViewAppView::DoActivateL( const TVwsViewId& /*aPrevViewId*/,TUid /*aCustomMessageId*/, const TDesC8& /*aCustomMessage*/) { if (!iContainer) { iContainer = new (ELeave) CMyViewAppContainer; iContainer->SetMopParent(this); iContainer->ConstructL( ClientRect() ); AppUi()->AddToStackL( *this, iContainer ); } // Message handling would take place here. }
, where
CMyViewAppView::DoActivateL()
is the
override for CAknView::DoActivateL()
for the application.
if (!iContainer)
checks to see if the
view already exists.
iContainer = new (ELeave) CMyViewAppContainer;
calls
the first phase constructor of the CCoeControl
-derived
class that provides the view.
iContainer->SetMopParent(this); sets the
context for the view being created. In this case, it assigns the CCoeControl
-derived
view to the view controller.
iContainer->ConstructL( ClientRect() )
calls
the second phase constructor of the CCoeControl
-derived
class that provides the view.
AppUi()->AddToStackL( *this, iContainer ); adds
the CCoeControl
-derived view to the control stack for key event handling.
The view architecture supports an automatic recovery mechanism if CAknView::DoActivateL()
leaves.
The Symbian platform calls CAknView::DoDeactivate()
in
the view that has left, reinstates the previous view of the application, and
returns to the view that was just displayed. If the application had no previous
view, it exits. If the application’s previous view was the same as the activating
view (that is, the view is reactivated with a new message), the application
attempts to recover to the default view.
In most cases, this mechanism removes the need to put any recovery mechanism
in the DoActivateL()
methods. The one situation where
you may consider something more complex is when the view can be reactivated
(that is, activated with a new message while already active). In this case,
the view may attempt a more complex strategy to preserve the existing state
if a leave happens during the attempt to handle the new message.
To destroy the CCoeControl
-derived control in a view
control, you must override CAknView::DoDeactivate()
. It
is called when the application exits, or another view has been activated and
the previous active window needs to be shut down. This order makes view switching
fast. In DoDeactivate
the view is removed from the stack
and therefore the view’s container and its controls are destroyed. This function
must not leave.
A common implementation is as follows:
void CMyViewAppView::DoDeactivate() { if ( iContainer ) { AppUi()->RemoveFromViewStack( *this, iContainer ); } delete iContainer; iContainer = NULL; }
, where
CMyViewAppView::DoDeactivateL()
is the
override for CAknView::DoDeactivateL()
for the application.
if (!iContainer)
checks to see if the
view already exists.
AppUi()->RemoveFromViewStack( *this, iContainer
); removes the CCoeControl
-derived view from
the control stack.
delete iContainer;
deletes the CCoeControl
-derived
view.