symbian 自定义控件

symbian 自定义控件

学习了一下自定义控件,及复合控件,自定义控件从  CCoeControl 继承过来,要实现 CCoeControl 的
void SizeChange() , void Draw(const TRect& aRect,const CCoeControl* aParent) 这两个虚方法,
自定义控件要用两阶构造方法,所以要添加 NewL 及 NewLC 方法,由于 Draw 方法需要用到两个参数,所以
在 NewL 时把两个参数要传入,下面是自定义控件的代码
头文件

#include <coecntrl.h>
class CSimControl : public CCoeControl  
{
public:
 
static CSimControl* NewL(const TRect& aRect,const CCoeControl* aParent);
 
static CSimControl* NewLC(const TRect& aRect,const CCoeControl* aParent);
public:
 CSimControl();
 
virtual ~CSimControl();
 
void Draw(const TRect& aRect) const;
    
void SizeChanged();
private:
 
void ConstructL(const TRect& aRect,const CCoeControl* aParent );
};

代码文件

#include "SimControl.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSimControl::CSimControl()
{
}
CSimControl::
~CSimControl()
{
}
CSimControl
* CSimControl::NewL( const TRect& aRect,const CCoeControl* aParent )
{
 CSimControl
* self = CSimControl::NewLC(aRect,aParent);
 CleanupStack::Pop();
 
return self;
}
CSimControl
* CSimControl::NewLC( const TRect& aRect,const CCoeControl* aParent )
{
 CSimControl
* self = new(ELeave)CSimControl();
 CleanupStack::PushL(self);
 self
->ConstructL(aRect,aParent);
 
return self;
}
void CSimControl::Draw( const TRect& aRect ) const
{
 CWindowGc
& gc = SystemGc();
 gc.Clear(aRect);
 gc.SetPenStyle(CGraphicsContext::ESolidPen);
 gc.SetPenColor(KRgbBlack);
 gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
 gc.SetBrushColor(KRgbBlack);
 gc.DrawEllipse(aRect);
}
void CSimControl::SizeChanged()
{
 
}
void CSimControl::ConstructL(const TRect& aRect,const CCoeControl* aParent )
{
 
if (aParent == NULL)
 {
  CreateWindowL();
 } 
else
 {
  SetContainerWindowL(
*aParent);
 }
 SetRect(aRect);
 ActivateL();
}
这里曾犯过一个错误,上面的代码 if(aParent ==NULL) 写成 if(aParent !=NULL) ,结果一直报错
在传统模式下调用代码

// INCLUDE FILES
#include "scContainer.h"
#include 
"SimControl.h"

#include 
<eiklabel.h>  // for example label control


// ================= MEMBER FUNCTIONS =======================

// ---------------------------------------------------------
// CscContainer::ConstructL(const TRect& aRect)
// EPOC two phased constructor
// ---------------------------------------------------------
//
void CscContainer::ConstructL(const TRect& aRect)
    {
    CreateWindowL();

    iLabel 
= new (ELeave) CEikLabel;
    iLabel
->SetContainerWindowL( *this );
    iLabel
->SetTextL( _L("Example View") );

    iToDoLabel 
= new (ELeave) CEikLabel;
    iToDoLabel
->SetContainerWindowL( *this );
    iToDoLabel
->SetTextL( _L("Add Your controls\n here") );
 
 
//iSimControl = CSimControl::NewL(aRect,NULL);
 
//iSimControl->SetContainerWindowL(*this);


 iCompoundControl 
= CCompoundControl::NewL(aRect,NULL);
 iCompoundControl
->SetContainerWindowL(*this);

    SetRect(aRect);
    ActivateL();
// error
    }

// Destructor
CscContainer::~CscContainer()
    {
    delete iLabel;
    delete iToDoLabel;
 
//delete iSimControl;
 delete iCompoundControl;
    }

// ---------------------------------------------------------
// CscContainer::SizeChanged()
// Called by framework when the view size is changed
// ---------------------------------------------------------
//
void CscContainer::SizeChanged()
    {
    
// TODO: Add here control resize code etc.
    iLabel->SetExtent( TPoint(10,10), iLabel->MinimumSize() );
    iToDoLabel
->SetExtent( TPoint(10,100), iToDoLabel->MinimumSize() );
 
//iSimControl->SetExtent(TPoint(10,10),iSimControl->MinimumSize());
 iCompoundControl->SetExtent(TPoint(10,10),TSize(200,100));
    }

// ---------------------------------------------------------
// CscContainer::CountComponentControls() const
// ---------------------------------------------------------
//
TInt CscContainer::CountComponentControls() const
    {
    
return 3// return nbr of controls inside this container
    }

// ---------------------------------------------------------
// CscContainer::ComponentControl(TInt aIndex) const
// ---------------------------------------------------------
//
CCoeControl* CscContainer::ComponentControl(TInt aIndex) const
    {
    
switch ( aIndex )
        {
        
case 0:
            
return iLabel;
        
case 1:
            
return iToDoLabel;
  
case 2:
   
return iCompoundControl;

        
default:
            
return NULL;
        }
    }

// ---------------------------------------------------------
// CscContainer::Draw(const TRect& aRect) const
// ---------------------------------------------------------
//
void CscContainer::Draw(const TRect& aRect) const
    {
    CWindowGc
& gc = SystemGc();
    
// TODO: Add your drawing code here
    
// example code...
    gc.SetPenStyle( CGraphicsContext::ENullPen );
    gc.SetBrushColor( KRgbGray );
    gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
    gc.DrawRect( aRect );
    }

// ---------------------------------------------------------
// CscContainer::HandleControlEventL(
//     CCoeControl* aControl,TCoeEvent aEventType)
// ---------------------------------------------------------
//
void CscContainer::HandleControlEventL(
    CCoeControl
* /*aControl*/,TCoeEvent /*aEventType*/)
    {
    
// TODO: Add your control event handler code here
    }

 

上面加粗的代码是该控件的代码,注释起来是因为测试复合控件时才注释起来

需要注意的是 SizeChange 方法,一定要写上 iSimControl->SetExtent(TPoint(10,10),iSimControl->MinimumSize());
否则显示不出来

复合控件代码
头文件

#include <coecntrl.h>
#include 
"SimControl.h"

class CCompoundControl : public CCoeControl  
{
public:
    
static CCompoundControl* NewL(const TRect& aRect,const CCoeControl* aParent);
    
static CCompoundControl* NewLC(const TRect& aRect,const CCoeControl* aParent);
    
~CCompoundControl();
public:
    CCompoundControl();
    
private:
    
    
void ConstructL(const TRect& aRect,const CCoeControl* aParent);
    
// 继承的方法
    TInt CountComponentControls() const;
    CCoeControl
* ComponentControl(TInt aIndex) const;
    
void Draw(const TRect& aRect) const;
    
void SizeChanged();
private:
    
void CalculateRects();
private:
    
//定义两个自定义控件
    CSimControl* iTop;
    CSimControl
* iBottom;

    TRect iTopRect;
    TRect iBottomRect;
private:
    
enum TComponentControls
    {
        ETop 
= 0,EBottom,ENumberOfControls
    };
};
 

代码文件

#include "CompoundControl.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCompoundControl::CCompoundControl()
{

}

CCompoundControl::
~CCompoundControl()
{
    delete iTop;
    delete iBottom;
}

CCompoundControl
* CCompoundControl::NewL( const TRect& aRect,const CCoeControl* aParent )
{
    CCompoundControl
* self = CCompoundControl::NewLC(aRect,aParent);
    CleanupStack::Pop();
    
return self;
}

CCompoundControl
* CCompoundControl::NewLC( const TRect& aRect,const CCoeControl* aParent )
{
    CCompoundControl
* self = new (ELeave) CCompoundControl();
    CleanupStack::PushL(self);
    self
->ConstructL(aRect,aParent);
    
return self;
}

TInt CCompoundControl::CountComponentControls() 
const
{
    
return ENumberOfControls;
}

CCoeControl
* CCompoundControl::ComponentControl( TInt aIndex ) const
{
    
switch(aIndex)
    {
    
case ETop:
        
return iTop;
        
break;
    
case EBottom:
        
return iBottom;
        
break;
    
default:
        
return NULL;
        
break;
    
    }
}

void CCompoundControl::Draw( const TRect& aRect ) const
{
    CWindowGc
& gc = SystemGc();
    gc.Clear(aRect);
}

void CCompoundControl::CalculateRects()
{
    TRect outerRect 
= Rect();
    
const TInt innerRectWidth = outerRect.Width();
    
const TInt innerRectHeight = outerRect.Height()/2;

    iTopRect.SetRect(outerRect.iTl,TSize(innerRectWidth,innerRectHeight));
    iBottomRect 
= iTopRect;
    iBottomRect.Move(
0,innerRectHeight);
}

void CCompoundControl::ConstructL(const TRect& aRect,const CCoeControl* aParent)
{
    
if (aParent==NULL)
    {
        CreateWindowL();
    }
else
    {
        SetContainerWindowL(
*aParent);
    }
    CalculateRects();
    iTop 
= CSimControl::NewL(aRect,this);
    iBottom 
= CSimControl::NewL(aRect,this);

    SetRect(aRect);
    ActivateL();
}

void CCompoundControl::SizeChanged()
{
  CalculateRects();
  iTop
->SetRect(iTopRect);
  iBottom
->SetRect(iBottomRect);
}
 

复合控件也是从 CCoeControl 继承过来

上面已有的代码中写有把复合控件添加到传统模式的代码

下面是把自定义控件添加到View模式下

添加到 view  模式下时,需要把 appUi 从 CAknViewAppUi 继承,传统模式下是从 CAknAppUi 继承,然后还需要写一个 从CAknView继承来的类,在 AppUi中添加该类的成员,并创建该类的实例,下面是一个view类的代码

头文件:

#include <aknview.h>
#include 
<SimControl.h>
#include 
<e32std.h>
#include 
<aknviewappui.h>
class CSimControlView : public CAknView  
{
public:
    
static CSimControlView* NewL();
    
static CSimControlView* NewLC();
    
~CSimControlView();
private:
    TUid Id() 
const;
    
void HandleCommandL(TInt aCommand);
    
void DoActivateL(
        
const TVwsViewId& aPrevViewId,
        TUid aCustomMessageId,
        
const TDesC8& aCustomMessage);
    
    
void DoDeactivate();
private:
    CSimControlView();
    
void ContructL();
private:
    CSimControl
* iSimControl;
    TUid iId;
};
 

从CAknView 继承时一定要重写 Id() ,DoActivateL(),DoDeactivate() 方法,Id()用于返回一个 view 的ID,DoActivateL是激活view时,DoDeactivate是不激活(由活动变成非活动)

代码文件:

#include "SimControlView.h"
#include 
"SIMPLECONTROLLX.RSG"
#include 
"sc.hrh"
#include 
"avkon.hrh"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSimControlView::CSimControlView()
{
   
}

CSimControlView::
~CSimControlView()
{
    
if (iSimControl)
    {
        delete iSimControl;
        iSimControl 
= NULL;
    }
}

CSimControlView
* CSimControlView::NewL()
{
    CSimControlView
* self = CSimControlView::NewLC();
    CleanupStack::Pop();
    
return self;
}

CSimControlView
* CSimControlView::NewLC()
{    
    CSimControlView
* self = new(ELeave) CSimControlView();
    CleanupStack::PushL(self);
    self
->ContructL();
    
return self;
}

/*
 返回视图的 id ,在视图切换时会用到此函数,一般都采用获取视图 id 的方式访问视图
ESimpleControlViewId ,是定义在 hrh 文件中的一个枚举值,也可以定义一个全局TUid 变量

*/
TUid CSimControlView::Id() 
const
{
    
return TUid::Uid(ESimpleControlViewId);
}

/*  这里一般都调用 appUi 的 HandleCommandL*/
void CSimControlView::HandleCommandL( TInt aCommand )
{
    
switch(aCommand)
    {
    
case EAknSoftkeyBack:
            AppUi()
->HandleCommandL(EEikCmdExit);
        
break;
    
default:
        AppUi()
->HandleCommandL(aCommand);
        
break;
    }
}

void CSimControlView::DoActivateL( const TVwsViewId& aPrevViewId, TUid aCustomMessageId, const TDesC8& aCustomMessage )
{
    
if (!iSimControl)
    {
        
this->iSimControl = CSimControl::NewL(ClientRect(),NULL);
        iSimControl
->SetMopParent(this);
        AppUi()
->AddToStackL(*this,iSimControl);
    }
    
}

void CSimControlView::DoDeactivate()
{
    
if (iSimControl)
    {
        AppUi()
->RemoveFromStack(iSimControl);
        delete iSimControl;
        iSimControl 
= NULL;
    }
}

void CSimControlView::ContructL()
{
    
//this->BaseConstructL(R_CONTROLS_VIEW1);
    
// 这里不太清楚为什么要传入一个资源 id
    
// 去掉这句也运行正常
    
//BaseConstructL();
}

下面是 appui的代码
头文件:

class CscAppUi : public CAknViewAppUi
    {
    
public// // Constructors and destructor

        
/**
        * EPOC default constructor.
        
*/      
        
void ConstructL();

        
/**
        * Destructor.
        
*/      
        
~CscAppUi();
        
    
public// New functions

    
public// Functions from base classes

    
private:
        
// From MEikMenuObserver
        void DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane);

    
private:
        
/**
        * From CEikAppUi, takes care of command handling.
        * @param aCommand command to be handled
        
*/
        
void HandleCommandL(TInt aCommand);

        
/**
        * From CEikAppUi, handles key events.
        * @param aKeyEvent Event to handled.
        * @param aType Type of the key event. 
        * @return Response code (EKeyWasConsumed, EKeyWasNotConsumed). 
        
*/
        
virtual TKeyResponse HandleKeyEventL(
            
const TKeyEvent& aKeyEvent,TEventCode aType);

    
private//Data
        CscContainer* iAppContainer; 
        CSimControlView
* iSimControlView;
        CCompoundControlView
* iCompoundControl;
       
        CAknNavigationControlContainer
* iNaviPanel;
        CAknTabGroup
*
                   iTabGroup;
        CAknNavigationDecorator
*        iDecoratedTabGroup;  // decorated 修饰的意思

    };

上面加粗部分的是 tab控件信息

代码文件:

// INCLUDE FILES
#include "scAppui.h"
#include 
"scContainer.h" 
#include 
<sc.rsg>
#include 
"sc.hrh"

#include 
<avkon.hrh>

// ================= MEMBER FUNCTIONS =======================
//
// ----------------------------------------------------------
// CscAppUi::ConstructL()
// 
// ----------------------------------------------------------
//
void CscAppUi::ConstructL()
    {
    BaseConstructL();

/*
    iAppContainer = new (ELeave) CscContainer;
    iAppContainer->SetMopParent( this );
    iAppContainer->ConstructL( ClientRect() );
    AddToStackL( iAppContainer );
        
*/


    
// 应该是取得状态面板
    CEikStatusPane* sp = StatusPane();
    iNaviPanel 
= (CAknNavigationControlContainer*)sp->ControlL(TUid::Uid(EEikStatusPaneUidNavi));
      
    
this->iDecoratedTabGroup = iNaviPanel->ResourceDecorator();
        
    
if (iDecoratedTabGroup)
    {
        iTabGroup 
= (CAknTabGroup*)iDecoratedTabGroup->DecoratedControl();      
    }

    iSimControlView 
= CSimControlView::NewL();
    AddViewL(iSimControlView);
    
    
/*    */
/*    */
    iCompoundControl 
= CCompoundControlView::NewL();
    AddViewL(iCompoundControl);
    
//SetDefaultViewL(*iCompoundControl);
    SetDefaultViewL(*iSimControlView);
    }

// ----------------------------------------------------
// CscAppUi::~CscAppUi()
// Destructor
// Frees reserved resources
// ----------------------------------------------------
//
CscAppUi::~CscAppUi()
    {
    
if (iAppContainer)
        {
        RemoveFromStack( iAppContainer );
        delete iAppContainer;
        }
   }

// ------------------------------------------------------------------------------
// CscAppUi::DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane)
//  This function is called by the EIKON framework just before it displays
//  a menu pane. Its default implementation is empty, and by overriding it,
//  the application can set the state of menu items dynamically according
//  to the state of application data.
// ------------------------------------------------------------------------------
//
void CscAppUi::DynInitMenuPaneL(
    TInt 
/*aResourceId*/,CEikMenuPane* /*aMenuPane*/)
    {
    }

// ----------------------------------------------------
// CscAppUi::HandleKeyEventL(
//     const TKeyEvent& aKeyEvent,TEventCode /*aType*/)
// takes care of key event handling
// ----------------------------------------------------
//
TKeyResponse CscAppUi::HandleKeyEventL(
    
const TKeyEvent& aKeyEvent,TEventCode aType)
    {
        
if (!iTabGroup)
        {
            
return EKeyWasNotConsumed;
        }
        TInt active 
= iTabGroup->ActiveTabIndex();
        TInt count  
= iTabGroup->TabCount();

        
switch(aKeyEvent.iCode)
        {
        
case EKeyLeftArrow:
            
if (active)
            {
                active
--;
                iTabGroup
->SetActiveTabByIndex(active);
                ActivateLocalViewL(TUid::Uid(iTabGroup
->TabIdFromIndex(active)));
            }
            
break;
        
case EKeyRightArrow:
            
if (active+1<count)
            {
                active
++;
                iTabGroup
->SetActiveTabByIndex(active);
                ActivateLocalViewL(TUid::Uid(iTabGroup
->TabIdFromIndex(active)));
            }
            
break;
        
default:
            
return EKeyWasNotConsumed;
            
break;

        }
        
return EKeyWasConsumed;
    }

// ----------------------------------------------------
// CscAppUi::HandleCommandL(TInt aCommand)
// takes care of command handling
// ----------------------------------------------------
//
void CscAppUi::HandleCommandL(TInt aCommand)
    {
    
switch ( aCommand )
        {
        
case EAknSoftkeyBack:
        
case EEikCmdExit:
            {
            Exit();
            
break;
            }
        
case EscCmdAppTest:
            {
            iEikonEnv
->InfoMsg(_L("test"));
            
break;
            }
        
// TODO: Add Your command handling code here

        
default:
            
break;      
        }
    }



// End of File 


核心代码是:

 iSimControlView = CSimControlView::NewL();
    AddViewL(iSimControlView);
    
    
/*    */
/*    */
    iCompoundControl 
= CCompoundControlView::NewL();
    AddViewL(iCompoundControl);
    
//SetDefaultViewL(*iCompoundControl);
    SetDefaultViewL(*iSimControlView);
 

这几句,创建一个 view 对像,然后通过 AddViewL 添加,如果去掉 tab 控件的代码,添加一个 view ,则效果和传统开发的效果一样

花了两天的时间终于把自定义控件搞好了,其中遇到不少问题,也都一一解决了,好不容易,又走了一步。

 代码下载:https://files.cnblogs.com/zziss/sc.rar



安平2009@原创
qi_jianzhou@126.com

原文地址:https://www.cnblogs.com/zziss/p/1658276.html