symbian自定义控件

来源:百度文库 编辑:神马文学网 时间:2024/04/19 19:15:33

一、定义

概述

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

#include

   

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

   

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(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()) != 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部件做如下变更:

  • CMyControl::Draw()必须调用DrawFocusFrame()以便绘制焦点矩形
  • CMyControl::DrawFocusFrame()是一个新方法,在其中绘制焦点框

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

{

CWindowGc& gc = SystemGc();

gc.SetBrushColor(KRgbBlue);

gc.Clear(Rect());

 

DrawFocusFrame(aRect);