Cocos2D-X 3.10通用窗口控件 Ctl_WinForm
可以自由拖拽的小窗口
#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);