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
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
{
// 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);