smallarmy  

自定义控件

摘自网上:

http://wiki.forum.nokia.com/index.php/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%A7%E4%BB%B6%EF%BC%9A_%E5%AE%9A%E4%B9%89%EF%BC%88%E4%B8%80%EF%BC%89

 

一、定义

概述

Symbian OS提供了大量现成的控件,但是有时还不够用。你可以通过从CCoeControl基类派生构造你自己的UI控件。

本例演示如何定义你自己的有一个CEikLabel的简单自定义控件。 派生自CCoeControl 并实现下述基本方法:

  • 构造
  • 布局
  • 大小
  • 绘制控件
  • 被包含的控件(若有的话)

 

MMP文件

下面的库文件是必须的:

LIBRARY euser.lib

LIBRARY apparc.lib

LIBRARY cone.lib

LIBRARY eikcore.lib

LIBRARY avkon.lib

LIBRARY commonengine.lib

LIBRARY eikcoctl.lib

LIBRARY gdi.lib

头文件

#include <coecntrl.h>

#include <eiklabel.h>

   

class CMyControl : public CCoeControl

{

public:

static CMyControl* NewL(const TRect& aRect,const CCoeControl* aParent=NULL);

static CMyControl* NewLC(const TRect& aRect,const CCoeControl* aParent=NULL);

virtual ~CMyControl();

   

public: // from CCoeControl

TSize MinimumSize();

   

private: // from CCoeControl

void Draw(const TRect& aRect) const;

void SizeChanged();

   

private: // own methods

CMyControl();

void ConstructL(const TRect& aRect,const CCoeControl* aParent = NULL);

   

private: // data

CEikLabel* iStatusText;

};

源代码

CMyControl* CMyControl::NewL(const TRect& aRect,const CCoeControl* aParent)

{

CMyControl* self = CMyControl::NewLC(aRect,aParent);

CleanupStack::Pop(self);

return self;

}

   

CMyControl* CMyControl::NewLC(const TRect& aRect,const CCoeControl* aParent)

{

CMyControl* self = new(ELeave) CMyControl();

CleanupStack::PushL(self);

self->ConstructL(aRect,aParent);

return self;

}

   

CMyControl::CMyControl()

{

}

   

CMyControl::~CMyControl()

{

// NOTE: Does not delete iStatusText because we do not own it

}

   

void CMyControl::ConstructL(const TRect& aRect,const CCoeControl* aParent)

{

// No owner, so create an own window

if(aParent == NULL)

{

CreateWindowL();

}

// Use Parent's window

else

{

// This is component in a compound control

SetContainerWindowL(*aParent);

}

   

// Initialize component array

InitComponentArrayL();

   

// Create contained controls

iStatusText = new (ELeave) CEikLabel;

iStatusText->SetContainerWindowL(*this);

iStatusText->SetTextL(_L("HelloWorld"));

   

// Store component to component array

Components().AppendLC(iStatusText);

CleanupStack::Pop(iStatusText);

   

SetRect(aRect); // or

//SetExtentToWholeScreen(); //NOTE: Can not see CBA buttons

   

// The application should call this function on

// all controls that are not components in a compound control

if(aParent == NULL)

{

ActivateL();

}

}

   

TSize CMyControl::MinimumSize()

{

// Get CEikLabel minium size and grow it

// that is this control MinimumSize.

// Custom control also needs a few other methods so it can be laid out

// and drawn. For example, custom controls usually implement MinimumSize(),

// SizeChanged() and Draw() methods.

   

// When using control in container control, set the minium size very small

TRect rect = iStatusText->MinimumSize();

rect.Grow(TSize(2,2));

return rect.Size();

   

// When using the control in a dialog, set the control size large

//return Rect().Size();

}

   

void CMyControl::SizeChanged()

{

// Responds to size changes to set the size and position of the contents

// of this control. For a simple control this might include text or

// graphics. For a compound control this sets the size and position of the

// component. It has an empty default implementation and should be

// implemented by the CCoeControl-derived class.

// The function is called whenever SetExtent(), SetSize(), SetRect(),

// SetCornerAndSize(), or SetExtentToWholeScreen() are called on

// the control.

if (iStatusText)

{

TRect labelRect(Rect());

labelRect.Shrink(TSize(5,2));

iStatusText->SetRect(labelRect);

}

}

   

void CMyControl::Draw(const TRect& /*aRect*/) const

{

CWindowGc& gc = SystemGc();

gc.SetBrushColor(KRgbBlue);

gc.Clear(Rect());

}

 

使用CCoeControl

自定义控件CMyControl被添加到了MultiViews例子(S60 3rd FP1)中,在.cpp中作如下修改:

void CMultiViewsView1::DoActivateL( const TVwsViewId& /*aPrevViewId*/,

TUid /*aCustomMessageId*/,

const TDesC8& /*aCustomMessage*/)

{

iControl = CMyControl::NewL(ClientRect());

}

   

void CMultiViewsView1::DoDeactivate()

{

if (iControl)

{

AppUi()->RemoveFromStack(iControl);

delete iControl;

iControl = NULL;

}

}

   

void CMultiViewsView1::HandleSizeChange( TInt aType )

{

if( iControl )

{

iControl->HandleResourceChange( aType );

if ( aType==KEikDynamicLayoutVariantSwitch )

{

TRect rect;

AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, rect);

iControl->SetRect(rect);

}

}

}

 

后置条件

CMyControl可以放在另一个CCoeControl(复合控件),或作为单独的控件而没有父控件。

 

 

从资源构造:

概要

这个代码片段演示如何从资源创建CCoeControl。本例扩展了代码片段自定义控件: 定义(一)

CMyControl::ConstructFromResourceL()用与CMyControl::ConstructL()同样的方式初始化控件,但参数从TResourceReader获得。资源读取器是一个从资源文件流读取字节的工具类;因此,读取必须以同样的顺序且数据大小必须与那些定义在资源结构声明中的相匹配。

MMP 文件

下面的能力(capabilities)和库(libraries)是必须的:

LIBRARY bafl.lib //TResourceReader

头文件

添加一个当从资源创建类时被调用的新函数,以及添加BARSREAD.H包含头文件。缺省构造函数CMyControl()应被移至public范围。

#include <BARSREAD.H>

   

public:

CMyControl();

void ConstructFromResourceL(TResourceReader& aReader);

源代码

这段代码为CEikLabel从资源读取文本。

void CMyControl::ConstructFromResourceL(TResourceReader& aReader)

{

// No parent owner, so create an own window

CreateWindowL();

   

// Initialize component array

InitComponentArrayL();

   

// Create contained controls

iStatusText = new (ELeave) CEikLabel;

iStatusText->SetContainerWindowL(*this);

   

// Read label from resource

TPtrC label = aReader.ReadTPtrC16();

iStatusText->SetTextL(label);

 

// Store component to component array

Components().AppendLC(iStatusText);

CleanupStack::Pop(iStatusText);

   

// Set component rect to CMultiViewsAppUi::ClientRect()

CMultiViewsAppUi* appui = (static_cast<CMultiViewsAppUi*>(iEikonEnv->AppUi()));

appui->ClientRect();

if (appui)

{

SetRect(appui->ClientRect());

}

 

ActivateL();

}

CMyControl部件资源customcontrol.rh文件

CMyControl部件的资源配置参数:

STRUCT CUSTOMCONTROL

{

LTEXT txt;

}

资源.rss文件

Multiviews样例应用资源文件作如下变更: multiviews.rss.

// New include that is our own component resource config

#include "customcontrol.rh"

   

// Defining resource for our component.

RESOURCE CUSTOMCONTROL r_custom_control

{

txt = STRING_r_custom_control;

}

STRING_r_custom_control定义在multiviews.rls.

 

从资源创建部件

创建资源读取器,经由缺省构造函数创建部件,然后调用ConstructFromResourceL()

// Creating control from resource

TResourceReader reader;

iEikonEnv->CreateResourceReaderLC(reader, R_CUSTOM_CONTROL);

iContainer2 = new (ELeave) CMyControl;

iContainer2->ConstructFromResourceL(reader);

iContainer2->SetRect(ClientRect());

CleanupStack::PopAndDestroy(); // reader

后置条件

CMyControl通过已定义资源参数被创建。

 

容器控件:

概述

这个代码片段演示如何创建一个拥有自定义控件的容器控件。例子演示如何用一个矩形框聚焦第一个部件及如何改变焦点。

本例扩展已存代码片段自定义控件: 定义(一) 容器控件存储其控件到CCoeControlArray中。

头文件

class CMyContainerControl : public CCoeControl

{

public:

static CMyContainerControl* NewL(const TRect& aRect);

static CMyContainerControl* NewLC(const TRect& aRect);

virtual ~CMyContainerControl();

   

private: // from CCoeControl

void Draw(const TRect& aRect) const;

void SizeChanged();

   

public: // own methods

// NOTE: Transfer ownership to CMyContainerControl

void AddControlL(CCoeControl* aControl,TInt aControlId);

void UpdateControls();

 

private: // own methods

CMyContainerControl();

void ConstructL(const TRect& aRect);

};

 

源代码

CMyContainerControl* CMyContainerControl::NewL(const TRect& aRect)

{

CMyContainerControl* self = CMyContainerControl::NewLC(aRect);

CleanupStack::Pop(self);

return self;

}

   

CMyContainerControl* CMyContainerControl::NewLC(const TRect& aRect)

{

CMyContainerControl* self = new(ELeave) CMyContainerControl();

CleanupStack::PushL(self);

self->ConstructL(aRect);

return self;

}

   

CMyContainerControl::CMyContainerControl()

{

}

   

CMyContainerControl::~CMyContainerControl()

{

}

   

void CMyContainerControl::ConstructL(const TRect& aRect)

{

// No parent owner, so create an own window

CreateWindowL();

 

// Initialize component array

InitComponentArrayL();

 

SetRect(aRect);

 

ActivateL();

}

   

void CMyContainerControl::SizeChanged()

{

UpdateControls();

}

   

void CMyContainerControl::UpdateControls()

{

TPoint position;

   

// Goes through all components of this container control

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

// If control is not visible, do not set it's position

if (!ctrl->IsVisible())

{

cursor.Next();

continue;

}

 

// Set position

ctrl->SetPosition(position);

   

// Set size

TSize size = ctrl->MinimumSize();

size.SetSize(Rect().Width(),size.iHeight);

ctrl->SetSize(size);

   

// Calculate position

position.iY += size.iHeight;

 

// Does control fit to view?

if (position.iY >= Rect().iBr.iY)

{

ctrl->MakeVisible(EFalse);

}

else

{

ctrl->MakeVisible(ETrue);

}

 

cursor.Next();

}

}

   

void CMyContainerControl::Draw(const TRect& /*aRect*/) const

{

CWindowGc& gc = SystemGc();

gc.SetBrushColor(KRgbBlack);

gc.Clear(Rect());

}

   

void CMyContainerControl::AddControlL(CCoeControl* aControl,TInt aControlId)

{

// NOTE: Transfer ownership of CCoeControl to CMyContainerControl

// Add control into container control

Components().AppendLC(aControl,aControlId);

CleanupStack::Pop(aControl);

   

// Focus first component

if (Components().Count()==1)

{

aControl->SetFocus(ETrue);

}

   

// Update control's position

UpdateControls();

}

SizeChanged函数

CMyContainerControl的大小改变时(例如: SetRect()被调用时),部件的位置必须再次计算。

void CMyContainerControl::SizeChanged()

{

// Sets new position of the components

UpdateControls();

}

聚焦部件

CMyControl部件做如下变更:

void CMyControl::Draw(const TRect& aRect) const

{

CWindowGc& gc = SystemGc();

gc.SetBrushColor(KRgbBlue);

gc.Clear(Rect());

 

DrawFocusFrame(aRect);

}

   

void CMyControl::DrawFocusFrame(const TRect& aRect) const

{

// Nothing to draw if not focused

if ( IsFocused() == EFalse )

return;

 

// Prep for draw

CWindowGc& gc = SystemGc();

gc.SetPenStyle( CGraphicsContext::ESolidPen );

gc.SetPenSize( TSize(KFocusFrameWidth,KFocusFrameWidth) );

gc.SetBrushStyle( CGraphicsContext::ENullBrush );

gc.SetPenColor( KRgbDarkGray );

 

// Draw the rounded rectangle

gc.DrawRoundRect( aRect, TSize( KFrameRoundRadius, KFrameRoundRadius ) );

}

后置条件

CMyContainerControl容器在列表中有一些CMyControl自定义控件。

 

 

聚焦:

概述

这个代码片段演示如何添加摁键事件处理到自定义的容器控件以及如何改变所选部件的焦点。

本例扩展已存代码片段自定义控件: 容器控件(三)。查看本文的"参见部分"以了解自定义控件系列的其它代码片段。

CMyContainerControl - 头文件

CMyContainerControl部件的头文件添加三个方法以便接收摁键事件和改变焦点。

private:

TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);

public:

void MoveFocusUp();

void MoveFocusDown();

CMultiViewsView1 - 源代码

CMyContainerControl必须加到控件栈中以便接收摁键事件AppUi()->AddToStackL().

// Create Compound control

iContainerControl = CMyContainerControl::NewL(ClientRect());

   

// Create control to the compound container

CMyControl* control1 = CMyControl::NewLC(ClientRect(),iContainerControl);

iContainerControl->AddControlL(control1,1);

CleanupStack::Pop(); //control 1

   

// Add the control to the control stack

AppUi()->AddToStackL(iContainerControl);

CMyContainerControl - 源代码

OfferKeyEventL()捕捉击键事件EKeyUpArrowEKeyDownArrow以便改变所选部件的焦点。 MoveFocusUp()MoveFocusDown()CCoeContainer::SetFocus()改变活动部件焦点到另一个部件。

TKeyResponse CMyContainerControl::OfferKeyEventL

(const TKeyEvent& aKeyEvent,TEventCode /*aType*/)

{

// Move focus

switch ( aKeyEvent.iCode )

{

case EKeyUpArrow:

{

MoveFocusUp();

DrawNow(); // Draw components again

return EKeyWasConsumed;

}

case EKeyDownArrow:

{

MoveFocusDown();

DrawNow(); // Draw components again

return EKeyWasConsumed;

}

default:

{

return EKeyWasNotConsumed;

}

}

}

   

void CMyContainerControl::MoveFocusUp()

{

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

CCoeControl* prevCtrl = NULL;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

if (ctrl->IsFocused())

{

if (prevCtrl)

{

// Set focus to previous control

ctrl->SetFocus(EFalse);

prevCtrl->SetFocus(ETrue);

break;

}

else

{

break; // First control is already focused

}

}

prevCtrl = ctrl;

cursor.Next();

}

}

   

void CMyContainerControl::MoveFocusDown()

{

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

CCoeControl* nextCtrl = NULL;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

if (ctrl->IsFocused())

{

cursor.Next();

nextCtrl = cursor.Control<CCoeControl>();

if (nextCtrl)

{

// Set focus to next control

ctrl->SetFocus(EFalse);

nextCtrl->SetFocus(ETrue);

break;

}

else

{

break; // Last control is already focused

}

}

cursor.Next();

}

}

绘制焦点

在自定义控件CMyControl::Draw()方法中绘制焦点矩形,Draw方法调用检查部件焦点的CMyControl::DrawFocusFrame()方法。若部件有焦点,就用CWindowGc::DrawRoundRect()来绘制。

后置条件

CMyContainerControl接受击键事件并显示活动部件焦点。

 

自定义滚动条:

概述

这个代码片段演示如何给有自定义控件的容器控件添加滚动条,以及如何只显示可见部件并在视图的顶部和底部搜查更多的可视部件。

本例扩展了已存代码片段自定义控件: 聚焦(四)。查看本文的"参见"部分以了解自定义控件系列的其它代码片段。

CMyContainerControl - 头文件

添加这些方法和成员数据到CMyContainerControl部件的头文件中。

MoveFocusUpL() 移动焦点寻求更多的部件以显示到视图顶部屏幕
MoveFocusDownL() 移动焦点寻求更多部件以显示到视图底部屏幕
UpdateScrollBarFrameL() 更新滚动条
ShowNextItem() 查找更多条目并在视图底部屏幕显示出来
ShowPrevItem() 查找更多条目并在视图顶部屏幕显示出来

#include <eiksbfrm.h>

   

private:

void ShowNextItem();

void ShowPrevItem();

void MoveFocusUpL();

void MoveFocusDownL();

void UpdateScrollBarFrameL();

private:

CEikScrollBarFrame* iScrollBarFrame;

TAknDoubleSpanScrollBarModel iHDsSbarModel;

TAknDoubleSpanScrollBarModel iVDsSbarModel;

TInt iFocusedIndex;

CMyContainerControl - 源代码

CMyContainerControl::ConstructL()中创建滚动条:

// Creating Scroll Bars

iScrollBarFrame = new ( ELeave ) CEikScrollBarFrame( this, NULL );

iScrollBarFrame->CreateDoubleSpanScrollBarsL( ETrue, EFalse );

iScrollBarFrame->SetTypeOfVScrollBar( CEikScrollBarFrame::EDoubleSpan );

iScrollBarFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,

CEikScrollBarFrame::EOff );

CMyContainerControl::UpdateScrollBarFrameL()中更新滚动条数据; 在添加部件到这个容器控件后,这个方法会在CMyContainerControl::AddControlL()中调用。

void CMyContainerControl::UpdateScrollBarFrameL()

{

TInt controlsHeight = 0; // Height of the controls

TInt height = 0; // This view height

 

// Calculate components height

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

controlsHeight += ctrl->MinimumSize().iHeight;

cursor.Next();

}

   

// This view height

height = Rect().Height();

 

// Set teh scrollbar visible if fields do not fit the screen

if( controlsHeight > height &&

iScrollBarFrame->VScrollBarVisibility() ==

CEikScrollBarFrame::EOff)

{

iScrollBarFrame->SetScrollBarVisibilityL(

CEikScrollBarFrame::EOff, // horizontal

CEikScrollBarFrame::EOn); // vertical

}

// Hide the scrollbar if fields fit the screen

else if ( controlsHeight <= height &&

iScrollBarFrame->VScrollBarVisibility() ==

CEikScrollBarFrame::EOn)

{

iScrollBarFrame->SetScrollBarVisibilityL(

CEikScrollBarFrame::EOff, // horizontal

CEikScrollBarFrame::EOff); // vertical

}

 

// Update scroll bar position

iVDsSbarModel.SetScrollSpan(Components().Count());

iVDsSbarModel.SetWindowSize(1);

iVDsSbarModel.SetFocusPosition(iFocusedIndex);

TEikScrollBarFrameLayout layout;

layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant;

TRect rect = Rect();

iScrollBarFrame->TileL(&iHDsSbarModel,&iVDsSbarModel,rect,rect,layout);

iScrollBarFrame->SetVFocusPosToThumbPos(iVDsSbarModel.FocusPosition());

}

CMyContainerControl::MoveFocusUpL()移动活动部件焦点,以及若达到屏幕顶部就请求显示更多部件。

void CMyContainerControl::MoveFocusUpL()

{

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

CCoeControl* prevCtrl = NULL;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

if (ctrl->IsFocused())

{

if (prevCtrl)

{

// Set focus to previous control

ctrl->SetFocus(EFalse);

prevCtrl->SetFocus(ETrue);

iFocusedIndex--;

 

// Focus is over the view?

if (iFocusedIndex > 0 && !prevCtrl->IsVisible())

{

ShowPrevItem();

}

break;

}

else

{

break; // First control is already focused

}

}

prevCtrl = ctrl;

cursor.Next();

}

   

UpdateScrollBarFrameL();

}

CMyContainerControl::MoveFocusDownL()移动活动部件焦点,以及若焦点到达屏幕底部就请求显示更多部件。

void CMyContainerControl::MoveFocusDownL()

{

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

CCoeControl* nextCtrl = NULL;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

if (ctrl && ctrl->IsFocused())

{

cursor.Next();

nextCtrl = cursor.Control<CCoeControl>();

if (nextCtrl)

{

// Set focus to next control

ctrl->SetFocus(EFalse);

nextCtrl->SetFocus(ETrue);

iFocusedIndex++;

 

// Focus is over the view?

if (!nextCtrl->IsVisible())

{

ShowNextItem();

}

break;

}

else

{

break; // Last control is already focused

}

}

cursor.Next();

}

   

UpdateScrollBarFrameL();

}


void CMyContainerControl::ShowNextItem()void CMyContainerControl::ShowPrevItem()查找更多的部件以便查看及设置到正确的位置。

void CMyContainerControl::ShowNextItem()

{

TPoint position;

   

// Goes throught all components of this container control

CCoeControlArray::TCursor cursor = Components().Begin();

CCoeControl* ctrl = NULL;

TBool focusedFound = EFalse;

while ((ctrl = cursor.Control<CCoeControl>()) != NULL)

{

if (ctrl && ctrl->IsFocused())

{

focusedFound = ETrue;

}

   

if (focusedFound)

{

// Set size

TSize size = ctrl->MinimumSize();

size.SetSize(Rect().Width(),size.iHeight);

ctrl->SetSize(size);

   

// Does it fit to the screen?

if ((position.iY + size.iHeight) >= Rect().iBr.iY)

{

ctrl->MakeVisible(EFalse);

focusedFound = EFalse; // Let rest components be MakeVisible(EFalse)

}

else

{

ctrl->MakeVisible(ETrue);

   

// Set position

ctrl->SetPosition(position);

 

// Store position of last component

position.iY += size.iHeight;

}

}

else

{

ctrl->MakeVisible(EFalse);

}

cursor.Next();

}

}

   

   

void CMyContainerControl::ShowPrevItem()

{

TPoint position;

position.iY = Rect().iBr.iY;

 

// Goes throught all components from the last -> to the first one

CCoeControlArray::TCursor cursor = Components().End();

CCoeControl* ctrl = NULL;

TBool focusedFound = EFalse;

while (cursor.Prev())

{

ctrl = cursor.Control<CCoeControl>();

if (ctrl && ctrl->IsFocused())

{

focusedFound = ETrue;

}

 

if (focusedFound)

{

// Set size

TSize size = ctrl->MinimumSize();

size.SetSize(Rect().Width(),size.iHeight);

ctrl->SetSize(size);

   

// Fix position

position.iY -= size.iHeight;

 

if ((position.iY) <= Rect().iTl.iY-2)

{

// Does not fit anymore

ctrl->MakeVisible(EFalse);

focusedFound = EFalse; // Let rest components be MakeVisible(EFalse)

}

else

{

ctrl->MakeVisible(ETrue);

   

// Set position

ctrl->SetPosition(position);

}

}

else

{

ctrl->MakeVisible(EFalse);

}

}

}

 

后置条件

自定义控件有滚动条演示视图中焦点的位置。当达到视图的底部或顶部将显示更多部件。

 

 

自定义对话框

 

概述

这个例子扩展了自定义控件例子自定义控件: 定义(一)。在本代码片段,CMyControl自定义控件添加到CAknDialog

MMP file

添加下面这个额外的库文件,因为用到了CAknDialog

LIBRARY eikdlg.lib

创建CMyDialog

定义一个实现CEikDialog::CreateCustomControlL()方法的自定义对话框。

这个方法在对话框中创建一个控件行。其后通过标识符控件ID访问该行。控件类型由Eikon控件工厂创建。若控件类型对于Eikon控件工厂是未知的,那么控件的构造必须由CreateCustomControlL()来处理。

CMyDialog对话框资源在multiviews.rss中:

RESOURCE DIALOG r_dialog

{

flags = EAknDialogGenericFullScreen;

buttons = R_AVKON_SOFTKEYS_OK_BACK;

items =

{

DLG_LINE

{

// CMyControl custom control type (defined in multiviews.hrh)

type = KMyCustomCtl;

// CMyControl custom control id (defined in multiviews.hrh)

id = KMyCustomCtlId;

control = CUSTOMCONTROL

{

txt = STRING_r_custom_control_dialog;

};

}

};

}

CMyDialog 对话框头文件定义了所需的CreateCustomControlL()方法:

#include <akndialog.h>

   

class CMyDialog : public CAknDialog

{

public:

static TInt RunDlgLD();

void PreLayoutDynInitL();

 

private:

SEikControlInfo CreateCustomControlL(TInt aControlType);

};

CMyDialog对话框实现:

#include "cmydialog.h"

#include "cmycontrol.h"

#include <MultiViews.rsg>

#include "MultiViews.hrh"

   

TInt CMyDialog::RunDlgLD()

{

CMyDialog* dlg = new (ELeave) CMyDialog;

return dlg->ExecuteLD(R_DIALOG);

}

   

void CMyDialog::PreLayoutDynInitL()

{

CMyControl* control = (CMyControl*)Control(KMyCustomCtlId);

// TODO: tune components if needed

}

   

SEikControlInfo CMyDialog::CreateCustomControlL(TInt aControlType)

{

SEikControlInfo controlInfo;

controlInfo.iControl = NULL ;

controlInfo.iTrailerTextId = 0 ;

controlInfo.iFlags = 0 ;

   

switch (aControlType)

{

// CMyControl custom control type (defined in multiviews.hrh)

case KMyCustomCtl:

{

controlInfo.iControl = new(ELeave)CMyControl();

break;

}

default:

break;

}

return controlInfo;

}

加到multiviews.hrh中的新枚举值:

// CMyControl custom control type in resource file

enum {KMyCustomCtl = KAknCtLastControlId };

// CMyControl custom control id in resource file

enum {KMyCustomCtlId = 0x503 };

调出对话框:

CMyDialog::RunDlgLD();

后置条件

CMyDialog由对话框资源来创建,且CMyControl通过调用CMyControl::ConstructFromResourceL()创建到对话框行中。 CMyDialog实现的CEikDialog::CreateCustomControlL()虚拟方法,创建自定义控件到对话框行中。

TODO: 如何使能对话框皮肤支持?

 

 
Copyright © 2019 阿军
Powered by .NET Core 3.0 Preview 8 on Linux
Powered by: 博客园 模板提供:沪江博客
博客园