Cocos2d-x学习笔记(十二)CCMenuItem详解

来源:互联网 发布:铝材下料软件 编辑:程序博客网 时间:2024/06/06 04:38

原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38948661


前言

我们上一篇笔记对CCMenu的实现进行了分析,这一节我们来看看CCMenuItem。

头文件

class CC_DLL CCMenuItem : public CCNodeRGBA{protected:    /** whether or not the item is selected     @since v0.8.2     */    bool m_bSelected; // 是否被选中    bool m_bEnabled; // 是否可用public:    CCMenuItem()    : m_bSelected(false)    , m_bEnabled(false)                , m_pListener(NULL)                , m_pfnSelector(NULL)    , m_nScriptTapHandler(0)    {}    virtual ~CCMenuItem();    // 默认创建方法    static CCMenuItem* create();    // 根据一个目标节点和选择事件创建    static CCMenuItem* create(CCObject *rec, SEL_MenuHandler selector);    // 根据一个目标节点和选择事件进行初始化    bool initWithTarget(CCObject *rec, SEL_MenuHandler selector);    // 返回当前菜单的矩形    CCRect rect();    // 激活当前的菜单项    virtual void activate();    // 将当前菜单项置于被选中时状态    virtual void selected();    // 取消当前菜单项选中状态    virtual void unselected();        /** Register menu handler script function */    virtual void registerScriptTapHandler(int nHandler);    virtual void unregisterScriptTapHandler(void);    int getScriptTapHandler() { return m_nScriptTapHandler; };    // 获取菜单项是否可用    virtual bool isEnabled();    // 设置菜单项是否可用    virtual void setEnabled(bool value);    virtual bool isSelected();              // 设置菜单项的目标节点和选择事件    void setTarget(CCObject *rec, SEL_MenuHandler selector);protected:    CCObject*       m_pListener; // 目标节点    SEL_MenuHandler    m_pfnSelector; // 选择事件    int             m_nScriptTapHandler;};/** @brief An abstract class for "label" CCMenuItemLabel items  Any CCNode that supports the CCLabelProtocol protocol can be added. Supported nodes: - CCBitmapFontAtlas - CCLabelAtlas - CCLabelTTF */class CC_DLL CCMenuItemLabel : public CCMenuItem{    /** the color that will be used to disable the item */    CC_PROPERTY_PASS_BY_REF(ccColor3B, m_tDisabledColor, DisabledColor);    /** Label that is rendered. It can be any CCNode that implements the CCLabelProtocol */    CC_PROPERTY(CCNode*, m_pLabel, Label);public:    CCMenuItemLabel()    : m_pLabel(NULL)    , m_fOriginalScale(0.0)    {}    virtual ~CCMenuItemLabel();    // 根据CCLabel、目标节点、点击事件创建一个紫菜单项    static CCMenuItemLabel * create(CCNode*label, CCObject* target, SEL_MenuHandler selector);    // 根据一个CCLabel创建一个子菜单项    static CCMenuItemLabel* create(CCNode *label);    // 初始化子菜单项    bool initWithLabel(CCNode* label, CCObject* target, SEL_MenuHandler selector);    // 设置菜单项显示文字    void setString(const char * label);    // 基类方法    virtual void activate();    virtual void selected();    virtual void unselected();    // 设置子菜单项是否可用    virtual void setEnabled(bool enabled);    protected:    ccColor3B    m_tColorBackup; // 备份颜色    float        m_fOriginalScale; // 缩放比例};/** @brief A CCMenuItemAtlasFont Helper class that creates a MenuItemLabel class with a LabelAtlas */class CC_DLL CCMenuItemAtlasFont : public CCMenuItemLabel{public:    CCMenuItemAtlasFont(){}    virtual ~CCMenuItemAtlasFont(){}    static CCMenuItemAtlasFont* create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap);    static CCMenuItemAtlasFont* create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector);    bool initWithString(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector);};class CC_DLL CCMenuItemFont : public CCMenuItemLabel{public:    CCMenuItemFont() : m_uFontSize(0), m_strFontName(""){}    virtual ~CCMenuItemFont(){}    // 设置/获取全局字体字号    static void setFontSize(unsigned int s);    static unsigned int fontSize();    // 设置/获取全局字体名称    static void setFontName(const char *name);    static const char *fontName();    // 仅通过文字创建一个子菜单项    static CCMenuItemFont * create(const char *value);    // 通过文字、目标节点、点击事件创建一个子菜单项    static CCMenuItemFont * create(const char *value, CCObject* target, SEL_MenuHandler selector);    // 初始化子菜单项    bool initWithString(const char *value, CCObject* target, SEL_MenuHandler selector);    // 设置/获取当前字体大小    void setFontSizeObj(unsigned int s);    unsigned int fontSizeObj();    // 设置/获取当前字体名称    void setFontNameObj(const char* name);    const char* fontNameObj();    protected:    void recreateLabel(); // 重新设置Label        unsigned int m_uFontSize; // 字体大小    std::string m_strFontName; // 字体名称};// Sprite子菜单项class CC_DLL CCMenuItemSprite : public CCMenuItem{    CC_PROPERTY(CCNode*, m_pNormalImage, NormalImage);    CC_PROPERTY(CCNode*, m_pSelectedImage, SelectedImage);    CC_PROPERTY(CCNode*, m_pDisabledImage, DisabledImage);public:    CCMenuItemSprite()    :m_pNormalImage(NULL)    ,m_pSelectedImage(NULL)    ,m_pDisabledImage(NULL)    {}    /**     * 创建一个子菜单项     *     * @param normalSprite 一般情况下的精灵     * @param selectedSprite 选中情况下的精灵     * @param disabledSprite 不可用情况下的精灵     */    static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite = NULL);    static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCObject* target, SEL_MenuHandler selector);    static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector);    // 初始化子菜单项    bool initWithNormalSprite(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector);        //    virtual void selected();    virtual void unselected();    virtual void setEnabled(bool bEnabled);    protected:    virtual void updateImagesVisibility();};// Image子菜单项class CC_DLL CCMenuItemImage : public CCMenuItemSprite{public:    CCMenuItemImage(){}    virtual ~CCMenuItemImage(){}        /**     * 创建一个子菜单项     *     * @param normalImage 一般情况下的图片地址     * @param selectedImage 选中情况下的图片地址     * @param disabledImage 不可用情况下的图片地址     */    static CCMenuItemImage* create(const char *normalImage, const char *selectedImage);    static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, const char *disabledImage);    static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, CCObject* target, SEL_MenuHandler selector);    static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector);        // 初始化一个子菜单项    bool init();    bool initWithNormalImage(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector);        // 设置一般/选中/不可用状态下的Sprite帧    void setNormalSpriteFrame(CCSpriteFrame* frame);    void setSelectedSpriteFrame(CCSpriteFrame* frame);    void setDisabledSpriteFrame(CCSpriteFrame* frame);    // 创建一个空子菜单项    static CCMenuItemImage* create();};// Toggle子菜单项class CC_DLL CCMenuItemToggle : public CCMenuItem{    CC_PROPERTY(unsigned int, m_uSelectedIndex, SelectedIndex);    CC_PROPERTY(CCArray*, m_pSubItems, SubItems);public:    CCMenuItemToggle()    : m_uSelectedIndex(0)    , m_pSubItems(NULL)                {}    virtual ~CCMenuItemToggle();        // 通过目标节点、点击事件、子菜单项数组创建一个子菜单项    static CCMenuItemToggle * createWithTarget(CCObject* target, SEL_MenuHandler selector, CCArray* menuItems);    // 通过目标节点、点击事件、子菜单项序列创建一个子菜单项    static CCMenuItemToggle* createWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, ...);    // 通过一个子菜单项创建一个子菜单项    static CCMenuItemToggle* create(CCMenuItem *item);    // 创建一个空子菜单项    static CCMenuItemToggle* create();    // 初始化子菜单项    bool initWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, va_list args);    bool initWithItem(CCMenuItem *item);    // 添加一个子菜单项    void addSubItem(CCMenuItem *item);    // 返回当前选中的子菜单项    CCMenuItem* selectedItem();    // 基类方法    virtual void activate();    virtual void selected();    virtual void unselected();    virtual void setEnabled(bool var);    };

通过头文件中描述我们不难发现,存在一个名为CCMenuItem的基类,来实现所有子菜单项的基本功能(继承自CCNode),然后由它又派生出了CCMenuItemLabel、CCMenuItemAtlasFont、CCMenuItemFont、CCMenuItemSprite、CCMenuItemImage、CCMenuItemToggle六种子菜单项:
CCMenuItemLabel是依据一个Label来创建的子菜单项,用于显示文本,也是CCMenuItemAtlasFont和CCMenuItemFont的基类
CCMenuItemAtlasFont是用于显示图片字体的子菜单项
CCMenuItemFont是用于创建一般文字子菜单项,极其简易,也可以自定义字体
CCMenuItemSprite是通过Sprite来创建子菜单项,需要传递一般状态、选中状态和不可用状态三种状态的Sprite
CCMenuItemImage是通过图片地址来创建子菜单项,也需要传递三种状态,它继承自CCMenuItemSprite,但相对于CCMenuItem而言操作更加简便
CCMenuItemToggle是一个比较有意思的子菜单项,它需要传递一系列子菜单项作为参数,用于实现点击后替换菜单项的效果,例如里面有A、B、C三个子菜单项,默认情况下是A,点一次之后变成了B,再点一次变成C,再点一次又变回A。
可是具体子菜单项又是怎样实现的呢?我们分析分析~

实现文件

static unsigned int _globalFontSize = kCCItemSize;static std::string _globalFontName = "Marker Felt";static bool _globalFontNameRelease = false;const unsigned int    kCurrentItem = 0xc0c05001;const unsigned int    kZoomActionTag = 0xc0c05002;const unsigned int    kNormalTag = 0x1;const unsigned int    kSelectedTag = 0x2;const unsigned int    kDisableTag = 0x3;//// CCMenuItem//CCMenuItem* CCMenuItem::create(){    return CCMenuItem::create(NULL, NULL);}CCMenuItem* CCMenuItem::create(CCObject *rec, SEL_MenuHandler selector){    CCMenuItem *pRet = new CCMenuItem(); // 通过构造函数创建一个默认的子菜单项    pRet->initWithTarget(rec, selector); // 初始化    pRet->autorelease(); // 添加到自动释放池中    return pRet;}bool CCMenuItem::initWithTarget(CCObject *rec, SEL_MenuHandler selector){    setAnchorPoint(ccp(0.5f, 0.5f)); // 设置锚点为中心    m_pListener = rec; // 设置监听器,即子菜单项所在目标节点    m_pfnSelector = selector; // 设置点击事件回调函数指针    m_bEnabled = true; // 设置为可用    m_bSelected = false; // 设置为未选中状态    return true;}CCMenuItem::~CCMenuItem(){    unregisterScriptTapHandler();}void CCMenuItem::selected(){    m_bSelected = true; // 修改为选中状态}void CCMenuItem::unselected(){    m_bSelected = false; // 修改为不可用状态}void CCMenuItem::registerScriptTapHandler(int nHandler){    unregisterScriptTapHandler();    m_nScriptTapHandler = nHandler;    LUALOG("[LUA] Add CCMenuItem script handler: %d", m_nScriptTapHandler);}void CCMenuItem::unregisterScriptTapHandler(void){    if (m_nScriptTapHandler)    {        CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptHandler(m_nScriptTapHandler);        LUALOG("[LUA] Remove CCMenuItem script handler: %d", m_nScriptTapHandler);        m_nScriptTapHandler = 0;    }}void CCMenuItem::activate(){    if (m_bEnabled) // 如果当前子菜单项可用    {        if (m_pListener && m_pfnSelector) // 且目标节点及点击事件存在        {            (m_pListener->*m_pfnSelector)(this);        }                if (kScriptTypeNone != m_eScriptType)        {            CCScriptEngineManager::sharedManager()->getScriptEngine()->executeMenuItemEvent(this);        }    }}void CCMenuItem::setEnabled(bool enabled){    m_bEnabled = enabled; // 设置可用状态}bool CCMenuItem::isEnabled(){    return m_bEnabled; // 返回可用状态}CCRect CCMenuItem::rect(){    return CCRectMake( m_obPosition.x - m_obContentSize.width * m_obAnchorPoint.x,                      m_obPosition.y - m_obContentSize.height * m_obAnchorPoint.y,                      m_obContentSize.width, m_obContentSize.height);}bool CCMenuItem::isSelected(){    return m_bSelected; // 返回选中状态}void CCMenuItem::setTarget(CCObject *rec, SEL_MenuHandler selector){    m_pListener = rec;    m_pfnSelector = selector;}////CCMenuItemLabel//const ccColor3B& CCMenuItemLabel::getDisabledColor(){    return m_tDisabledColor; // 返回不可用该状态文字颜色}void CCMenuItemLabel::setDisabledColor(const ccColor3B& var){    m_tDisabledColor = var; // 设置不可用状态下文字颜色}CCNode *CCMenuItemLabel::getLabel(){    return m_pLabel; // 返回子菜单项的Label}void CCMenuItemLabel::setLabel(CCNode* var){    if (var) // 如果待设置Label不为空    {        addChild(var); // 添加Label        var->setAnchorPoint(ccp(0, 0)); // 将锚点设置为左下角        setContentSize(var->getContentSize()); // 将子菜单项大小设置为Label大小    }        if (m_pLabel) // 如果当前Label不为空    {        removeChild(m_pLabel, true); // 移除并清空当前Label    }        m_pLabel = var; // 重新复制Label}CCMenuItemLabel * CCMenuItemLabel::create(CCNode*label, CCObject* target, SEL_MenuHandler selector){    CCMenuItemLabel *pRet = new CCMenuItemLabel();    pRet->initWithLabel(label, target, selector);    pRet->autorelease();    return pRet;}CCMenuItemLabel* CCMenuItemLabel::create(CCNode *label){    CCMenuItemLabel *pRet = new CCMenuItemLabel();    pRet->initWithLabel(label, NULL, NULL);    pRet->autorelease();    return pRet;}bool CCMenuItemLabel::initWithLabel(CCNode* label, CCObject* target, SEL_MenuHandler selector){    CCMenuItem::initWithTarget(target, selector);    m_fOriginalScale = 1.0f; // 默认缩放系数为1,代表没有缩放    m_tColorBackup = ccWHITE; // 默认字体颜色为白色,本分一下    setDisabledColor(ccc3(126,126,126)); // 设置不可用状态文字    this->setLabel(label); // 设置Label        setCascadeColorEnabled(true); // 后续Label中讲到    setCascadeOpacityEnabled(true);        return true;}CCMenuItemLabel::~CCMenuItemLabel(){}void CCMenuItemLabel::setString(const char * label){    dynamic_cast<CCLabelProtocol*>(m_pLabel)->setString(label); // 设置Label文字    this->setContentSize(m_pLabel->getContentSize()); // 重新设置子菜单项大小}void CCMenuItemLabel::activate(){    if(m_bEnabled)    {        this->stopAllActions(); // 停止所有动作        this->setScale( m_fOriginalScale ); // 设为默认缩放        CCMenuItem::activate(); // 调用基类的方法    }}void CCMenuItemLabel::selected(){    if(m_bEnabled) // 如果子菜单项可用才执行随后的方法    {        CCMenuItem::selected();                CCAction *action = getActionByTag(kZoomActionTag); // 获取缩放动作        if (action) // 如果正在执行动作        {            this->stopAction(action); // 停止动作        }        else        {            m_fOriginalScale = this->getScale(); // 保存当前大小        }                CCAction *zoomAction = CCScaleTo::create(0.1f, m_fOriginalScale * 1.2f); // 创建放大动作        zoomAction->setTag(kZoomActionTag); // 设置Tag        this->runAction(zoomAction); // 执行缩放动作    }}void CCMenuItemLabel::unselected(){    if(m_bEnabled)    {        CCMenuItem::unselected(); // 调用基类方法        this->stopActionByTag(kZoomActionTag); // 停止缩放动作        CCAction *zoomAction = CCScaleTo::create(0.1f, m_fOriginalScale); // 创建缩小动作        zoomAction->setTag(kZoomActionTag);        this->runAction(zoomAction);    }}void CCMenuItemLabel::setEnabled(bool enabled){    if( m_bEnabled != enabled )  // 如果待设置状态与当前状态不一样才执行操作    {        if(enabled == false) // 如果状态为不可用,则先备份当前可用颜色,然后将Label设置为不可用颜色        {            m_tColorBackup = dynamic_cast<CCRGBAProtocol*>(m_pLabel)->getColor();            dynamic_cast<CCRGBAProtocol*>(m_pLabel)->setColor(m_tDisabledColor);        }        else        { // 将Label恢复为备份颜色            dynamic_cast<CCRGBAProtocol*>(m_pLabel)->setColor(m_tColorBackup);        }    }    CCMenuItem::setEnabled(enabled); // 设置为不可用}////CCMenuItemAtlasFont//CCMenuItemAtlasFont * CCMenuItemAtlasFont::create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap){    return CCMenuItemAtlasFont::create(value, charMapFile, itemWidth, itemHeight, startCharMap, NULL, NULL);}CCMenuItemAtlasFont * CCMenuItemAtlasFont::create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector){    CCMenuItemAtlasFont *pRet = new CCMenuItemAtlasFont();    pRet->initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap, target, selector);    pRet->autorelease();    return pRet;}bool CCMenuItemAtlasFont::initWithString(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector){    CCAssert( value != NULL && strlen(value) != 0, "value length must be greater than 0");    CCLabelAtlas *label = new CCLabelAtlas();    label->initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap);    label->autorelease();    if (CCMenuItemLabel::initWithLabel(label, target, selector))    {        // do something ?    }    return true;}////CCMenuItemFont//void CCMenuItemFont::setFontSize(unsigned int s){    _globalFontSize = s;}unsigned int CCMenuItemFont::fontSize(){    return _globalFontSize;}void CCMenuItemFont::setFontName(const char *name){    if (_globalFontNameRelease) // 如果当前已有字体    {        _globalFontName.clear(); // 清空字体名称    }    _globalFontName = name; // 重新赋值字体名称    _globalFontNameRelease = true; // 标记为已有字体}const char * CCMenuItemFont::fontName(){    return _globalFontName.c_str();}CCMenuItemFont * CCMenuItemFont::create(const char *value, CCObject* target, SEL_MenuHandler selector){    CCMenuItemFont *pRet = new CCMenuItemFont();    pRet->initWithString(value, target, selector);    pRet->autorelease();    return pRet;}CCMenuItemFont * CCMenuItemFont::create(const char *value){    CCMenuItemFont *pRet = new CCMenuItemFont();    pRet->initWithString(value, NULL, NULL);    pRet->autorelease();    return pRet;}bool CCMenuItemFont::initWithString(const char *value, CCObject* target, SEL_MenuHandler selector){    // 确保传参有效    CCAssert( value != NULL && strlen(value) != 0, "Value length must be greater than 0");        m_strFontName = _globalFontName;    m_uFontSize = _globalFontSize;        CCLabelTTF *label = CCLabelTTF::create(value, m_strFontName.c_str(), (float)m_uFontSize);    if (CCMenuItemLabel::initWithLabel(label, target, selector))    {        // do something ?    }    return true;}void CCMenuItemFont::recreateLabel(){    // 重新创建一个Label,然后设置    CCLabelTTF *label = CCLabelTTF::create(dynamic_cast<CCLabelProtocol*>(m_pLabel)->getString(),                                                     m_strFontName.c_str(), (float)m_uFontSize);    this->setLabel(label);}void CCMenuItemFont::setFontSizeObj(unsigned int s){ //设置字体大小后重新创建    m_uFontSize = s;    recreateLabel();}unsigned int CCMenuItemFont::fontSizeObj(){    return m_uFontSize;}void CCMenuItemFont::setFontNameObj(const char* name){    m_strFontName = name;    recreateLabel();}const char* CCMenuItemFont::fontNameObj(){    return m_strFontName.c_str();}////CCMenuItemSprite//CCNode * CCMenuItemSprite::getNormalImage(){    return m_pNormalImage;}void CCMenuItemSprite::setNormalImage(CCNode* pImage){    if (pImage != m_pNormalImage) // 如果需要替换的节点和当前节点不同    {        if (pImage) // 如果节点不为空        {            addChild(pImage, 0, kNormalTag); // 添加节点            pImage->setAnchorPoint(ccp(0, 0)); // 设置锚点为左下角        }        if (m_pNormalImage) // 移除之前的一般状态Sprite        {            removeChild(m_pNormalImage, true);        }        m_pNormalImage = pImage; // 设置一般状态Sprite        this->setContentSize(m_pNormalImage->getContentSize()); // 重置大小        this->updateImagesVisibility(); // 刷新可见性    }}CCNode * CCMenuItemSprite::getSelectedImage(){    return m_pSelectedImage;}void CCMenuItemSprite::setSelectedImage(CCNode* pImage){ // 同setNormalImage    if (pImage != m_pNormalImage)    {        if (pImage)        {            addChild(pImage, 0, kSelectedTag);            pImage->setAnchorPoint(ccp(0, 0));        }        if (m_pSelectedImage)        {            removeChild(m_pSelectedImage, true);        }        m_pSelectedImage = pImage;        this->updateImagesVisibility();    }}CCNode * CCMenuItemSprite::getDisabledImage(){    return m_pDisabledImage;}void CCMenuItemSprite::setDisabledImage(CCNode* pImage){ // 同setNormalImage    if (pImage != m_pNormalImage)    {        if (pImage)        {            addChild(pImage, 0, kDisableTag);            pImage->setAnchorPoint(ccp(0, 0));        }        if (m_pDisabledImage)        {            removeChild(m_pDisabledImage, true);        }        m_pDisabledImage = pImage;        this->updateImagesVisibility();    }}////CCMenuItemSprite//CCMenuItemSprite * CCMenuItemSprite::create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite){    return CCMenuItemSprite::create(normalSprite, selectedSprite, disabledSprite, NULL, NULL);}CCMenuItemSprite * CCMenuItemSprite::create(CCNode* normalSprite, CCNode* selectedSprite, CCObject* target, SEL_MenuHandler selector){    return CCMenuItemSprite::create(normalSprite, selectedSprite, NULL, target, selector);}CCMenuItemSprite * CCMenuItemSprite::create(CCNode *normalSprite, CCNode *selectedSprite, CCNode *disabledSprite, CCObject *target, SEL_MenuHandler selector){    CCMenuItemSprite *pRet = new CCMenuItemSprite();    pRet->initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, target, selector);     pRet->autorelease();    return pRet;}bool CCMenuItemSprite::initWithNormalSprite(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector){    CCMenuItem::initWithTarget(target, selector);     setNormalImage(normalSprite);    setSelectedImage(selectedSprite);    setDisabledImage(disabledSprite);    if(m_pNormalImage)    {        this->setContentSize(m_pNormalImage->getContentSize());    }        setCascadeColorEnabled(true);    setCascadeOpacityEnabled(true);        return true;}/** @since v0.99.5 */void CCMenuItemSprite::selected(){    CCMenuItem::selected(); // 调用基类方法    if (m_pNormalImage) // 如果一般状态Sprite不为空    {        if (m_pDisabledImage) // 如果不可用状态Sprite不为空        {            m_pDisabledImage->setVisible(false); // 不可用状态Sprite设为不可见        }        if (m_pSelectedImage) // 如果选中状态Sprite不为空        {            m_pNormalImage->setVisible(false);  // 一般状态Sprite设为不可见            m_pSelectedImage->setVisible(true); // 选中状态Sprite设为可见        }        else        {            m_pNormalImage->setVisible(true); // 一般状态Sprite设为可见        }    }}void CCMenuItemSprite::unselected(){ // 同selected    CCMenuItem::unselected();    if (m_pNormalImage)    {        m_pNormalImage->setVisible(true);        if (m_pSelectedImage)        {            m_pSelectedImage->setVisible(false);        }        if (m_pDisabledImage)        {            m_pDisabledImage->setVisible(false);        }    }}void CCMenuItemSprite::setEnabled(bool bEnabled){ // 如果状态不一样,调用基类方法,并刷新可见性    if( m_bEnabled != bEnabled )     {        CCMenuItem::setEnabled(bEnabled);        this->updateImagesVisibility();    }}// Helper void CCMenuItemSprite::updateImagesVisibility(){    if (m_bEnabled) // 可用状态,默认一般状态Sprite显示,其他隐藏    {        if (m_pNormalImage)   m_pNormalImage->setVisible(true);        if (m_pSelectedImage) m_pSelectedImage->setVisible(false);        if (m_pDisabledImage) m_pDisabledImage->setVisible(false);    }    else    {        if (m_pDisabledImage) // 不可用状态,修改仅不可用状态Sprite显示,其他隐藏        {            if (m_pNormalImage)   m_pNormalImage->setVisible(false);            if (m_pSelectedImage) m_pSelectedImage->setVisible(false);            if (m_pDisabledImage) m_pDisabledImage->setVisible(true);        }        else // 选中状态,修改仅选中状态Sprite显示,其他隐藏        {            if (m_pNormalImage)   m_pNormalImage->setVisible(true);            if (m_pSelectedImage) m_pSelectedImage->setVisible(false);            if (m_pDisabledImage) m_pDisabledImage->setVisible(false);        }    }}////// CCMenuItemImage///CCMenuItemImage* CCMenuItemImage::create(){    CCMenuItemImage *pRet = new CCMenuItemImage();    if (pRet && pRet->init())    {        pRet->autorelease();        return pRet;    }    CC_SAFE_DELETE(pRet);    return NULL;}bool CCMenuItemImage::init(void){    return initWithNormalImage(NULL, NULL, NULL, NULL, NULL);}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage){    return CCMenuItemImage::create(normalImage, selectedImage, NULL, NULL, NULL);}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, CCObject* target, SEL_MenuHandler selector){    return CCMenuItemImage::create(normalImage, selectedImage, NULL, target, selector);}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector){    CCMenuItemImage *pRet = new CCMenuItemImage();    if (pRet && pRet->initWithNormalImage(normalImage, selectedImage, disabledImage, target, selector))    {        pRet->autorelease();        return pRet;    }    CC_SAFE_DELETE(pRet);    return NULL;}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, const char *disabledImage){    CCMenuItemImage *pRet = new CCMenuItemImage();    if (pRet && pRet->initWithNormalImage(normalImage, selectedImage, disabledImage, NULL, NULL))    {        pRet->autorelease();        return pRet;    }    CC_SAFE_DELETE(pRet);    return NULL;}bool CCMenuItemImage::initWithNormalImage(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector){ // 创建3个Sprite,分别设置成三种不同状态下该显示的图片    CCNode *normalSprite = NULL;    CCNode *selectedSprite = NULL;    CCNode *disabledSprite = NULL;    if (normalImage)    {        normalSprite = CCSprite::create(normalImage);    }    if (selectedImage)    {        selectedSprite = CCSprite::create(selectedImage);    }        if(disabledImage)    {        disabledSprite = CCSprite::create(disabledImage);    }    return initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, target, selector);}//// Setter of sprite frames//void CCMenuItemImage::setNormalSpriteFrame(CCSpriteFrame * frame){    setNormalImage(CCSprite::createWithSpriteFrame(frame));}void CCMenuItemImage::setSelectedSpriteFrame(CCSpriteFrame * frame){    setSelectedImage(CCSprite::createWithSpriteFrame(frame));}void CCMenuItemImage::setDisabledSpriteFrame(CCSpriteFrame * frame){    setDisabledImage(CCSprite::createWithSpriteFrame(frame));}//// MenuItemToggle//void CCMenuItemToggle::setSubItems(CCArray* var){    CC_SAFE_RETAIN(var);    CC_SAFE_RELEASE(m_pSubItems);    m_pSubItems = var; // 设置轮播数组}CCArray* CCMenuItemToggle::getSubItems(){    return m_pSubItems; // 返回轮播数组}CCMenuItemToggle * CCMenuItemToggle::createWithTarget(CCObject* target, SEL_MenuHandler selector, CCArray* menuItems){    CCMenuItemToggle *pRet = new CCMenuItemToggle();    pRet->CCMenuItem::initWithTarget(target, selector);    pRet->m_pSubItems = CCArray::create(); // 创建按默认数组    pRet->m_pSubItems->retain();        for (unsigned int z=0; z < menuItems->count(); z++)    { // 添加子菜单项        CCMenuItem* menuItem = (CCMenuItem*)menuItems->objectAtIndex(z);        pRet->m_pSubItems->addObject(menuItem);    }        pRet->m_uSelectedIndex = UINT_MAX; // 将默认的选中项设置为第一个    pRet->setSelectedIndex(0);    return pRet;}CCMenuItemToggle * CCMenuItemToggle::createWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, ...){    va_list args;    va_start(args, item);    CCMenuItemToggle *pRet = new CCMenuItemToggle();    pRet->initWithTarget(target, selector, item, args);    pRet->autorelease();    va_end(args);    return pRet;}CCMenuItemToggle * CCMenuItemToggle::create(){    CCMenuItemToggle *pRet = new CCMenuItemToggle();    pRet->initWithItem(NULL);    pRet->autorelease();    return pRet;}bool CCMenuItemToggle::initWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, va_list args){    CCMenuItem::initWithTarget(target, selector);    this->m_pSubItems = CCArray::create();    this->m_pSubItems->retain();    int z = 0;    CCMenuItem *i = item;    while(i)     {        z++;        m_pSubItems->addObject(i);        i = va_arg(args, CCMenuItem*);    }    m_uSelectedIndex = UINT_MAX;    this->setSelectedIndex(0);    return true;}CCMenuItemToggle* CCMenuItemToggle::create(CCMenuItem *item){    CCMenuItemToggle *pRet = new CCMenuItemToggle();    pRet->initWithItem(item);    pRet->autorelease();    return pRet;}bool CCMenuItemToggle::initWithItem(CCMenuItem *item){    CCMenuItem::initWithTarget(NULL, NULL);    setSubItems(CCArray::create());    if (item)    {        m_pSubItems->addObject(item);    }    m_uSelectedIndex = UINT_MAX;    this->setSelectedIndex(0);        setCascadeColorEnabled(true);    setCascadeOpacityEnabled(true);        return true;}void CCMenuItemToggle::addSubItem(CCMenuItem *item){    m_pSubItems->addObject(item); // 添加一个子菜单项进入轮播数组}CCMenuItemToggle::~CCMenuItemToggle(){    CC_SAFE_RELEASE(m_pSubItems);}void CCMenuItemToggle::setSelectedIndex(unsigned int index){    if( index != m_uSelectedIndex && m_pSubItems->count() > 0 ) // 如果待设置项不等于当前项,且轮播数组大于0    {        m_uSelectedIndex = index; // 设置选中项        CCMenuItem *currentItem = (CCMenuItem*)getChildByTag(kCurrentItem); // 获取当前选中项        if( currentItem ) // 如果当前选中项存在        {            currentItem->removeFromParentAndCleanup(false); // 从父类中移除但不清空        }        CCMenuItem* item = (CCMenuItem*)m_pSubItems->objectAtIndex(m_uSelectedIndex); // 选出轮播数组中对应项        this->addChild(item, 0, kCurrentItem); // 添加至屏幕中        CCSize s = item->getContentSize(); // 获取其大小        this->setContentSize(s); // 重置大小        item->setPosition( ccp( s.width/2, s.height/2 ) ); // 设置坐标    }}unsigned int CCMenuItemToggle::getSelectedIndex(){    return m_uSelectedIndex; // 获取当前选中项}void CCMenuItemToggle::selected(){    CCMenuItem::selected(); // 调用基类方法    ((CCMenuItem*)(m_pSubItems->objectAtIndex(m_uSelectedIndex)))->selected(); // 调用选中项的选中方法}void CCMenuItemToggle::unselected(){    CCMenuItem::unselected();    ((CCMenuItem*)(m_pSubItems->objectAtIndex(m_uSelectedIndex)))->unselected();}void CCMenuItemToggle::activate(){    // update index    if( m_bEnabled ) // 如果当前可用    {        unsigned int newIndex = (m_uSelectedIndex + 1) % m_pSubItems->count();        this->setSelectedIndex(newIndex);    }    CCMenuItem::activate();}void CCMenuItemToggle::setEnabled(bool enabled){    if (m_bEnabled != enabled)    {        CCMenuItem::setEnabled(enabled);        if(m_pSubItems && m_pSubItems->count() > 0)        {            CCObject* pObj = NULL;            CCARRAY_FOREACH(m_pSubItems, pObj)            {                CCMenuItem* pItem = (CCMenuItem*)pObj;                pItem->setEnabled(enabled);            }        }    }}CCMenuItem* CCMenuItemToggle::selectedItem(){    return (CCMenuItem*)m_pSubItems->objectAtIndex(m_uSelectedIndex);}
由于重复的代码比较多,不少地方也就没有一一注释了,仅在第一次出现时进行了注释。
看完了实现代码我们不难发现,对于Label菜单项的实现,是将Label添加至菜单中,直接对Label进行相应修改以达到目的,而Sprite菜单项的三种状态则对应3个不同的Sprite,在不同状态下仅仅让屏幕上只显示其中一个。

结言

通过这几篇学习笔记我们不难发现,不少控件的实现并不难,只要我们肯想,很多东西我们完全可以自己实现出来,在本次笔记中出现了不少和Label有关的东西,在下一篇笔记中,我们将一起学习。
0 0