zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    31天重构学习笔记28. 为布尔方法命名
    .NET 技术社区之我见(中文篇)
    31天重构学习笔记26. 避免双重否定
    31天重构学习笔记25. 引入契约式设计
    31天重构学习笔记20. 提取子类
    31天重构学习笔记18. 使用条件判断代替异常
    31天重构学习笔记19. 提取工厂类
    31天重构学习笔记24. 分解复杂判断
    31天重构学习笔记23. 引入参数对象
    31天重构学习笔记17. 提取父类
  • 原文地址:https://www.cnblogs.com/zziss/p/1658276.html
Copyright © 2011-2022 走看看