Cocos2D-X 3.10通用窗口控件 Ctl_WinForm

本文介绍了一个可自由拖拽的小窗口组件实现,该组件基于Cocos2d-x开发,支持自定义窗口大小、颜色等属性,并提供了子节点添加功能及触摸事件处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以自由拖拽的小窗口

 

#define RS_BREAK_IF(RF)        if(RF) break

 

 

/////////////////////////

//CTL_WinForm.h

////////////////////////
class Ctl_WinForm : public Sprite
{
public:
    static Ctl_WinForm * create();
    static Ctl_WinForm * create(std::string &_title, Color4B _title_color, float _title_height, Color4B _layer_tile_color, float _win_width, float _win_height, Color4B _win_color);
    Ctl_WinForm();
    virtual ~Ctl_WinForm();
    virtual bool init();
    virtual bool init(std::string &_title, Color4B _title_color, float _title_height, Color4B _layer_tile_color, float _win_width, float _win_height, Color4B _win_color);    // 初始化


    //////////////////////////////////////////////////////////////////////////
    // 控制功能
public:
    void SetTitle(std::string _title);
    void SetTitleColor(Color4B _color);
    void SetLayerTitleColor(Color4B _color);
    void SetWinFormSize(float _width, float _height, float _title_height);
    void SetWinFormColor(Color4B _color);

    //////////////////////////////////////////////////////////////////////////
    // 增加 addChild_winform
    virtual void addChild_winform(Node * child);
    virtual void addChild_winform(Node * child, int localZOrder);
    virtual void addChild_winform(Node* child, int localZOrder, int tag);
    virtual void addChild_winform(Node* child, int localZOrder, const std::string &name);
private:
    //////////////////////////////////////////////////////////////////////////
    // 布置控件
    bool LayoutControl(std::string &_title, Color4B _title_color, float _title_height, Color4B _layer_tile_color, float _win_width, float _win_height, Color4B _win_color);


    //////////////////////////////////////////////////////////////////////////
    // Layer 控件
    cocos2d::LayerColor * layer_win;
    cocos2d::LayerColor * layer_title;

    // Label 控件
    cocos2d::Label * label_title;

    //////////////////////////////////////////////////////////////////////////
    // 坐标变量
    cocos2d::Point currentPoint;    // 当前坐标
    cocos2d::Point offsetRange;        // 移动偏移

    //////////////////////////////////////////////////////////////////////////
    // layer_win 防穿透
    bool swallow;

    //////////////////////////////////////////////////////////////////////////
    // 静态数组 窗口管理
    static std::vector<Ctl_WinForm *> vec_winform;

    //////////////////////////////////////////////////////////////////////////
    // 触屏监听 函数
    bool onTouchBegan(Touch * _touch, Event * _event);
    void onTouchMoved(Touch * _touch, Event * _event);
    void onTouchEnded(Touch * _touch, Event * _event);

    void moveLayer(Point _offset);
};

 

/////////////////////////

//CTL_WinForm.cpp

////////////////////////


//////////////////////////////////////////////////////////////////////////
// 静态数组 窗口管理
std::vector<Ctl_WinForm *> Ctl_WinForm::vec_winform;


Ctl_WinForm * Ctl_WinForm::create()
{
    Ctl_WinForm * sprite = new (std::nothrow) Ctl_WinForm;
    if (sprite && sprite->init())
    {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}

Ctl_WinForm * Ctl_WinForm::create(std::string &_title, Color4B _title_color, float _title_height, Color4B _layer_tile_color, float _win_width, float _win_height, Color4B _win_color)
{
    Ctl_WinForm * sprite = new (std::nothrow) Ctl_WinForm;
    if (sprite && sprite->init(_title, _title_color, _title_height, _layer_tile_color, _win_width, _win_height, _win_color))
    {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}


Ctl_WinForm::Ctl_WinForm()
{
    layer_win = nullptr;    // Layer 控件
    layer_title = nullptr;

    currentPoint = Point::ZERO;    // 当前坐标
    offsetRange = Point::ZERO;    // 移动偏移

    vec_winform.push_back(this);    // 注册窗口
}

Ctl_WinForm::~Ctl_WinForm()
{
    // 删除窗口
    std::vector<Ctl_WinForm *>::iterator it = vec_winform.begin();
    for (; it != vec_winform.end(); it++)
    {
        if (*it == this)
        {
            vec_winform.erase(it);
            break;
        }
    }
}


bool Ctl_WinForm::init()
{
    return init(std::string("unknow")
        , Color4B(51, 51, 51, 255)
        , 30.0f
        , Color4B(255, 153, 51, 255)
        , 600
        , 400
        , Color4B(153, 204, 204, 255));
}


bool Ctl_WinForm::init(std::string &_title, Color4B _title_color, float _title_height, Color4B _layer_tile_color, float _win_width, float _win_height, Color4B _win_color)
{
    if (!Sprite::init())
        return false;

    do
    {
        //////////////////////////////////////////////////////////////////////////
        // 布置控件
        RS_BREAK_IF(LayoutControl(_title, _title_color, _title_height, _layer_tile_color, _win_width, _win_height, _win_color) == false);

        return true;

    } while (0);

    //////////////////////////////////////////////////////////////////////////
    // 日志省略

    return false;
}

//////////////////////////////////////////////////////////////////////////
// 控制功能

void Ctl_WinForm::SetTitle(std::string _title)
{
    label_title->setString(_title);
}
void Ctl_WinForm::SetTitleColor(Color4B _color)
{
    label_title->setColor(Color3B(_color));
}
void Ctl_WinForm::SetLayerTitleColor(Color4B _color)
{
    layer_title->setColor(Color3B(_color));
}
void Ctl_WinForm::SetWinFormSize(float _width, float _height, float _title_height)
{
    layer_win->setContentSize(Size(_width, _height));
    layer_title->setContentSize(Size(_width, _title_height));
}
void Ctl_WinForm::SetWinFormColor(Color4B _color)
{
    layer_win->setColor(Color3B(_color));
}

//////////////////////////////////////////////////////////////////////////
// 增加 addChild_winform
void Ctl_WinForm::addChild_winform(Node * child)
{
    if (layer_win != nullptr)
    {
        layer_win->addChild(child);
    }
}
void Ctl_WinForm::addChild_winform(Node * child, int localZOrder)
{
    if (layer_win != nullptr)
    {
        layer_win->addChild(child, localZOrder);
    }
}
void Ctl_WinForm::addChild_winform(Node* child, int localZOrder, int tag)
{
    if (layer_win != nullptr)
    {
        layer_win->addChild(child, localZOrder, tag);
    }
}
void Ctl_WinForm::addChild_winform(Node* child, int localZOrder, const std::string &name)
{
    if (layer_win != nullptr)
    {
        layer_win->addChild(child, localZOrder, name);
    }
}

bool Ctl_WinForm::LayoutControl(std::string &_title, Color4B _title_color, float _title_height, Color4B _layer_tile_color, float _win_width, float _win_height, Color4B _win_color)
{
    do
    {
        //////////////////////////////////////////////////////////////////////////
        // 获取窗口信息(可视尺寸、起始点、中心点)
        Size visible = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        Point center = Point(visible.width * 0.5f + origin.x, visible.height * 0.5f + origin.y);

        //////////////////////////////////////////////////////////////////////////
        // 窗体
        layer_win = LayerColor::create(_win_color, _win_width, _win_height);
        layer_win->setPosition(0, 0);
        this->addChild(layer_win, 1);

        //////////////////////////////////////////////////////////////////////////
        // 标题栏
        layer_title = LayerColor::create(_layer_tile_color, _win_width, _title_height);
        layer_title->setPosition(0, _win_height);
        this->addChild(layer_title, 2);

        //////////////////////////////////////////////////////////////////////////
        // 标题
        label_title = Label::createWithTTF(_title, std::string("fonts/msyh.ttc"), 16);
        label_title->setIgnoreAnchorPointForPosition(false);
        label_title->setAnchorPoint(Point::ZERO);
        label_title->setColor(Color3B(_title_color));
        label_title->setPosition(10, 6);
        layer_title->addChild(label_title, 1);

        //////////////////////////////////////////////////////////////////////////
        // 触屏监听
        auto listener = EventListenerTouchOneByOne::create();
        listener->setSwallowTouches(true);
        listener->onTouchBegan = CC_CALLBACK_2(Ctl_WinForm::onTouchBegan, this);
        listener->onTouchMoved = CC_CALLBACK_2(Ctl_WinForm::onTouchMoved, this);
        listener->onTouchEnded = CC_CALLBACK_2(Ctl_WinForm::onTouchEnded, this);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

        return true;

    } while (0);
    // 日志省略
    return false;
}

bool Ctl_WinForm::onTouchBegan(Touch* _touch, Event* _event)
{
    do
    {
        RS_BREAK_IF(layer_win == nullptr);
        RS_BREAK_IF(layer_title == nullptr);

        Point P = this->getParent()->convertToNodeSpace(_touch->getLocation());
        Rect R = layer_title->getBoundingBox();
        Rect R_2 = layer_win->getBoundingBox();

        // 调整窗口显示顺序
        if (R.containsPoint(P)== true || R_2.containsPoint(P) == true)
        {
            for (auto it : vec_winform)
                it->setLocalZOrder(1);
            this->setLocalZOrder(2);
        }

        // 拖动功能
        if (R.containsPoint(P) == true)
        {            
            swallow = false;
            offsetRange = Point::ZERO;
            currentPoint = P;

            return true;
        }

        // layer_win 防穿透
        if (R_2.containsPoint(P) == true)
        {
            swallow = true;
            return true;
        }

    } while (0);
    return false;
}
void Ctl_WinForm::onTouchMoved(Touch* _touch, Event* _event)
{
    do
    {
        RS_BREAK_IF(swallow == true);    // layer_win 防穿透

        Point P = _touch->getLocation();

        if (currentPoint != P)
        {
            Rect R = this->getParent()->getBoundingBox();
            if (R.containsPoint(P) == true)
            {
                offsetRange = P - currentPoint;
                currentPoint = P;
                moveLayer(offsetRange);
            }
        }

        return;

    } while (0);
}

void Ctl_WinForm::moveLayer(Point _offset)
{
    do
    {
        // layer_title
        Point np = layer_title->getPosition() + _offset;
        layer_title->setPosition(np);

        // layer_win
        layer_win->setPosition(layer_title->getPosition() - Point(0, layer_win->getContentSize().height));

    } while (0);

}

void Ctl_WinForm::onTouchEnded(Touch* _touch, Event* _event)
{
    currentPoint = Point::ZERO;
    offsetRange = Point::ZERO;
}

 

 

///////////////////////////////////////

//使用方式

Ctl_WinForm * rs_winform = Ctl_WinForm::create();

Sprite * _example = Sprite::create(...);

rs_winform ->addChild_winform(_example );

this->addChild(rs_winform);

參考了一下NeHe 的教程, 在 cocos2d-x 2.0 上可以做點小手腳在 Windows 上全屏顯示! 參考了一下NeHe 的教程, 在 cocos2d-x 2.0 上可以做點小手腳在 Windows 上全屏顯示! 主要修改兩個檔案: CCEGLView.h CCEGLView.cpp 它們在工程里的位置是 libcocos2d->platform->win32 先打開 CCEGLView.h 在 public: 底下加上一個新功能: void setFullScreen(bool flag); 另外在 private: 里加上一個新變數: bool m_bFullScreen; 接下來是 CCEGLView.cpp: 在 Constructor 加上 m_bFullScreen 的初始值: CCEGLView::CCEGLView() : m_bCaptured(false) , m_hWnd(NULL) , m_hDC(NULL) , m_hRC(NULL) , m_lpfnAccelerometerKeyHook(NULL) , m_bFullScreen(false) 再加上我們的 setFullScreen(): void CCEGLView::setFullScreen(bool flag) { m_bFullScreen = flag; } 然後在 Create() 里, 把CreateWindowEx() 那段改成下邊這樣: /////////////// FULLSCREEN HACK - BEGIN DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style DWORD dwStyle = WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX; // Window Style if (m_bFullScreen) { DEVMODE dmScreenSettings; // Device Mode memset(&dmScreenSettings;,0,sizeof(dmScreenSettings)); // Makes Sure Memory&#39;s Cleared dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure dmScreenSettings.dmPelsWidth = w; // Selected Screen Width dmScreenSettings.dmPelsHeight = h; // Selected Screen Height dmScreenSettings.dmBitsPerPel = 32; // Selected Bits Per Pixel dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. if (ChangeDisplaySettings(&dmScreenSettings;,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { // If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode. if (MessageBox(NULL, L"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?",L"cocos2d-x",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) { setFullScreen(false); // back to windowed mode } else { // Pop Up A Message Box Letting User Know The Program Is Closing. MessageBox(NULL,L"Program Will Now Close.",L"ERROR",MB_OK|MB_ICONSTOP); return FALSE; // Return FALSE } } else // yeah! we are in fullscreen { dwExStyle = WS_EX_APPWINDOW; dwStyle=WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; //ShowCursor(FALSE); RECT rect; rect.left=(long)0; // Set Left Value To 0 rect.right=(long)w; // Set Right Value To Requested Width rect.top=(long)0; // Set Top Value To 0 rect.bottom=(long)h; // Set Bottom Value To Requested Height AdjustWindowRectEx(&rect;, dwStyle, FALSE, dwExStyle); // Adjust To True Requested Size } } /////////////// FULLSCREEN HACK - END // create window m_hWnd = CreateWindowEx( dwExStyle, // Extended Style For The Window kWindowClassName, // Class Name wszBuf, // Window Title dwStyle, // Defined Window Style 0, 0, // Window Position 0, // Window Width 0, // Window Height NULL, // No Parent Window NULL, // No Menu hInstance, // Instance NULL ); CC_BREAK_IF(! m_hWnd); 基本上這樣已搞定. 最後在我們自己項目的 main.cpp 里選擇全屏即可: AppDelegate app; CCEGLView& eglView = CCEGLView::sharedOpenGLView(); eglView.setFullScreen(true); eglView.setViewName("Hello Tests"); eglView.setFrameSize(1920, 1080); 要注意事項: - eglView.setFullScreen(true) 一定要在 eglView.setViewName("xxx") 前面. - eglView.setFrameSize(1920, 1080) 設定的大小, 一定要是顯卡可以支持的. - 不能再用CCDirector::sharedDirector()->enableRetinaDisplay(true)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值