Files
EzUI/sources/Control.cpp

1793 lines
45 KiB
C++
Raw Normal View History

2026-01-24 22:42:46 +08:00
#include "Control.h"
#include "ScrollBar.h"
#include "Spacer.h"
#include "IFrame.h"
namespace ezui {
inline bool __IsValid(int value) {
return value != 0;
}
inline bool __IsValid(WORD value) {
return value != 0;
}
inline bool __IsValid(BYTE value) {
return value != 0;
}
inline bool __IsValid(float value) {
return std::abs(value) > EZUI_FLOAT_EPSILON;
}
inline bool __IsValid(const Image* value) {
return value != NULL;
}
inline bool __IsValid(const Color& value) {
return value.GetValue() != 0;
}
inline bool __IsValid(const UIString& value) {
return !value.empty();
}
inline bool __IsValid(const std::wstring& value) {
return !value.empty();
}
inline bool __IsValid(StrokeStyle value) {
return value != StrokeStyle::None;
}
inline bool __IsValid(HCURSOR value) {
return value != NULL;
}
//是否是像素单位
inline bool __IsPx(const UIString& num, float& outNum) {
size_t pos = num.find("px");
if (pos != 0 && pos == num.size() - 2) {
outNum = std::stof(num.substr(0, pos).c_str());
return true;
}
return false;
}
//字符串转数值
inline float __ToFloat(const UIString& numStr) {
float value;
if (__IsPx(numStr, value)) {//以px为单位
return value;
}
value = std::atof(numStr.c_str());
if (numStr.rfind("%") != std::string::npos) {//判断是不是百分比
value = value / 100.0f;//如果是百分比则返回小数点(0.0f~1.0f)
}
return value;//直接转数值返回
}
//处理url(d:/imgs/aa.png)路径
inline Image* __MakeImage(UIString value) {
value = value.replace("\"", "");//删除双引号;
auto pos1 = value.find("(");
auto pos2 = value.find(")");
if (pos1 != std::string::npos && pos2 != std::string::npos) {
//background-image:url(res/images/xxx.png)的方式
value = value.substr(pos1 + 1, pos2 - pos1 - 1);
}
return Image::Make(value);
}
//构建边框信息并回调
inline void __MakeBorder(UIString str, Border& bd, const std::function<void(float)>& callback) {
size_t pos1 = str.find('(');
size_t pos2 = str.find(')');
if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1) {
//删除括号内的空格
std::string inside = str.substr(pos1 + 1, pos2 - pos1 - 1);
inside.erase(std::remove(inside.begin(), inside.end(), ' '), inside.end());
str = str.substr(0, pos1 + 1) + inside + str.substr(pos2);
}
auto values = str.split(" ");
for (auto& v : values) {
float num;
if (v == "dashed") {
bd.Style = StrokeStyle::Dash;
continue;
}
else if (v == "solid") {
bd.Style = StrokeStyle::Solid;
continue;
}
else if (v == "none") {
bd.Style = StrokeStyle::None;
continue;
}
else if (__IsPx(v, num)) {
callback(num);
continue;
}
else
{
bool isGood = false;
Color color = Color::Make(v, &isGood);
if (isGood) {
bd.Color = color;
}
}
}
}
};
namespace ezui {
#define UI_SUPER_STYLE_BINDFUNC(_type,_filed) _type Control:: ##Get ##_filed(ControlState _state) { \
if (_state == ControlState::None) { \
_state = this->State; \
}\
##_type _##_filed;\
if ((_state & ControlState::Checked) == ControlState::Checked) {\
_##_filed = this->GetStyle(ControlState::Checked).##_filed;\
if (__IsValid(_##_filed)) {\
return _##_filed;\
}\
}\
if(this->IsEnabled()){ \
if ((_state & ControlState::Active) == ControlState::Active) {\
_##_filed = this->GetStyle(ControlState::Active).##_filed;\
if (__IsValid(_##_filed)) {\
return _##_filed;\
}else{\
_##_filed = this->GetStyle(ControlState::Hover).##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
}\
if ((_state & ControlState::Hover) == ControlState::Hover) {\
_##_filed = this->GetStyle(ControlState::Hover).##_filed;\
if (__IsValid(_##_filed)) {\
return _##_filed;\
}\
}\
}else {\
_##_filed = this->GetStyle(ControlState::Disabled).##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
_##_filed = this->GetStyle(ControlState::Static).##_filed; \
if (__IsValid(_##_filed)) {\
return _##_filed; \
}\
Control* parentCtrl = this->Parent; \
while (parentCtrl){ \
_##_filed = parentCtrl->GetStyle(ControlState::Static).##_filed; \
if (__IsValid(_##_filed)) {\
break; \
}\
parentCtrl = parentCtrl->Parent; \
}\
return _##_filed; \
}\
#define UI_STYLE_BINDFUNC(_type,_filed) _type Control:: ##Get ##_filed(ControlState _state) { \
if (_state == ControlState::None) {\
_state = this->State;\
}\
##_type _##_filed;\
if ((_state & ControlState::Checked) == ControlState::Checked) {\
_##_filed = this->GetStyle(ControlState::Checked).##_filed;\
if (__IsValid(_##_filed))return _##_filed;\
}\
if(this->IsEnabled()){ \
if ((_state & ControlState::Active) == ControlState::Active) {\
_##_filed = this->GetStyle(ControlState::Active).##_filed;\
if (__IsValid(_##_filed)){\
return _##_filed;\
}else{\
_##_filed = this->GetStyle(ControlState::Hover).##_filed; \
if (__IsValid(_##_filed))return _##_filed; \
}\
}\
if ((_state & ControlState::Hover) == ControlState::Hover) {\
_##_filed = this->GetStyle(ControlState::Hover).##_filed;\
if (__IsValid(_##_filed))return _##_filed;\
}\
}else {\
_##_filed = this->GetStyle(ControlState::Disabled).##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
return this->GetStyle(ControlState::Static).##_filed;;\
}\
#define UI_BORDER_BINDFUNC(_type,_filed1,_filed) _type Control:: ##Get ##_filed1 ##_filed(ControlState _state) { \
if (_state == ControlState::None) {\
_state = this->State;\
}\
##_type _##_filed;\
if ((_state & ControlState::Checked) == ControlState::Checked) {\
_##_filed = this->GetStyle(ControlState::Checked).##_filed1.##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
if(this->IsEnabled()){ \
if ((_state & ControlState::Active) == ControlState::Active) {\
_##_filed = this->GetStyle(ControlState::Active).##_filed1.##_filed;\
if (__IsValid(_##_filed)){\
return _##_filed;\
}else{\
_##_filed = this->GetStyle(ControlState::Hover).##_filed1.##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
}\
if ((_state & ControlState::Hover) == ControlState::Hover) {\
_##_filed = this->GetStyle(ControlState::Hover).##_filed1.##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
}else {\
_##_filed = this->GetStyle(ControlState::Disabled).##_filed1.##_filed;\
if (__IsValid(_##_filed)) return _##_filed;\
}\
return this->GetStyle(ControlState::Static).##_filed1.##_filed; \
}\
UI_BORDER_BINDFUNC(int, Border, TopLeftRadius);
UI_BORDER_BINDFUNC(int, Border, TopRightRadius);
UI_BORDER_BINDFUNC(int, Border, BottomRightRadius);
UI_BORDER_BINDFUNC(int, Border, BottomLeftRadius);
UI_BORDER_BINDFUNC(int, Border, Left);
UI_BORDER_BINDFUNC(int, Border, Top);
UI_BORDER_BINDFUNC(int, Border, Right);
UI_BORDER_BINDFUNC(int, Border, Bottom);
UI_BORDER_BINDFUNC(Color, Border, Color);
UI_BORDER_BINDFUNC(StrokeStyle, Border, Style);
UI_STYLE_BINDFUNC(Color, BackColor);
UI_STYLE_BINDFUNC(Image*, ForeImage);
UI_STYLE_BINDFUNC(Image*, BackImage);
UI_STYLE_BINDFUNC(float, Angle);
UI_STYLE_BINDFUNC(HCURSOR, Cursor);
UI_SUPER_STYLE_BINDFUNC(int, FontSize);
UI_SUPER_STYLE_BINDFUNC(Color, ForeColor);
UI_SUPER_STYLE_BINDFUNC(std::wstring, FontFamily);
WindowData* Control::GetPublicData()
{
return (WindowData*)UI_GET_USERDATA(Hwnd());
}
IFrame* Control::GetFrame()
{
IFrame* frame = NULL;
Control* parent = this;
//依次往上父控件看看有没有当前控件是否在内联页面中
while (parent)
{
if (frame = dynamic_cast<IFrame*>(parent)) {
break;
}
parent = parent->Parent;
}
return frame;
}
Control::Control(Object* parentObject) :Object(parentObject)
{
}
void Control::OnChildPaint(PaintEventArgs& args)
{
ViewControls.clear();
//绘制子控件
Rect rect(0, 0, Width(), Height());
for (auto& it : m_controls) {
if (rect.IntersectsWith(it->GetRect())) {
ViewControls.push_back(it);
}
it->SendEvent(args);
}
}
void Control::OnPaint(PaintEventArgs& args)
{
OnBackgroundPaint(args);//先绘制背景
OnForePaint(args);//再绘制前景
}
void Control::OnBackgroundPaint(PaintEventArgs& e)
{
Color backgroundColor = this->GetBackColor();
Image* backgroundImage = this->GetBackImage();
if (backgroundColor.GetValue() != 0) {
e.Graphics.SetColor(backgroundColor);
e.Graphics.FillRectangle(RectF{ 0,0,(float)m_rect.Width,(float)m_rect.Height });
}
if (backgroundImage != NULL) {
e.Graphics.DrawImage(backgroundImage, RectF{ 0,0,(float)m_rect.Width,(float)m_rect.Height });
}
}
void Control::OnForePaint(PaintEventArgs& e) {
Image* foreImage = this->GetForeImage();
if (foreImage) {
e.Graphics.DrawImage(foreImage, RectF{ 0,0,(float)m_rect.Width,(float)m_rect.Height });
}
}
void Control::OnBorderPaint(PaintEventArgs& e, const Border& border)
{
if (border.Color.GetValue() == 0) return;//边框无效颜色不绘制
if (border.Style == StrokeStyle::None)return;//未指定边框风格 不允许绘制
int borderLeft = border.Left;
int borderTop = border.Top;
int borderRight = border.Right;
int borderBottom = border.Bottom;
int topLeftRadius = border.TopLeftRadius;
int topRightRadius = border.TopRightRadius;
int bottomRightRadius = border.BottomRightRadius;
int bottomLeftRadius = border.BottomLeftRadius;
//指定边框风格
e.Graphics.SetStrokeStyle(border.Style);
//规则的矩形
if (topLeftRadius == 0 && topRightRadius == 0 && bottomLeftRadius == 0 && bottomRightRadius == 0) {
bool hasBorder = borderLeft || borderTop || borderRight || borderBottom;
if (!hasBorder) return;//边框为0不绘制
e.Graphics.SetColor(border.Color);
if (borderLeft > 0) {
float half = borderLeft / 2.0f;
e.Graphics.DrawLine(PointF{ half, 0 }, PointF{ half, (float)Height() }, borderLeft);
}
if (borderTop > 0) {
float half = borderTop / 2.0f;
e.Graphics.DrawLine(PointF{ 0, half }, PointF{ (float)Width(), half }, borderTop);
}
if (borderRight > 0) {
float half = borderRight / 2.0f;
e.Graphics.DrawLine(PointF{ (float)Width() - half, 0 }, PointF{ (float)Width() - half, (float)Height() }, borderRight);
}
if (borderBottom > 0) {
float half = borderBottom / 2.0f;
e.Graphics.DrawLine(PointF{ 0, (float)Height() - half }, PointF{ (float)Width(), (float)Height() - half }, borderBottom);
}
}
else {
int value1 = borderLeft > borderTop ? borderLeft : borderTop;
int value2 = borderRight > borderBottom ? borderRight : borderBottom;
int maxBorder = value1 > value2 ? value1 : value2;
if (maxBorder <= 0) return;
float half = maxBorder / 2.0f;
e.Graphics.SetColor(border.Color);
#define max(a,b) (((a) > (b)) ? (a) : (b))
// 减去半个边框宽度,确保所有边线和圆角都在控件内
auto shrink = [&](int r) -> float {
return max(0.0f, (float)r - half);
};
RectangleGeometry rr(
RectF(half, half, Width() - half * 2.0f, Height() - half * 2.0f),
shrink(topLeftRadius),
shrink(topRightRadius),
shrink(bottomRightRadius),
shrink(bottomLeftRadius)
);
e.Graphics.DrawGeometry(rr.Get(), maxBorder);
}
}
ControlStyle& Control::GetStyle(const ControlState& _state) {
if ((_state & ControlState::Disabled) == ControlState::Disabled) {
return this->DisabledStyle;
}
else if ((_state & ControlState::Hover) == ControlState::Hover) {
return this->HoverStyle;
}
else if ((_state & ControlState::Active) == ControlState::Active) {
return this->ActiveStyle;
}
return this->Style;
}
void Control::SetAttribute(const UIString& attrName, const UIString& attrValue)
{
__super::SetAttribute(attrName, attrValue);
do
{
if (this->ApplyStyleProperty(attrName, attrValue)) {
break;
}
if (attrName == "name" || attrName == "id") {
this->Name = attrValue;
break;
}
if (attrName == "location") {
auto arr = attrValue.split(",");
int x = __ToFloat(arr[0]);
int y = __ToFloat(arr[1]);
this->SetLocation(Point(x, y));
break;
}
if (attrName == "size") {
if (attrValue == "auto") {
this->SetAutoWidth(true);
this->SetAutoHeight(true);
}
else {
auto arr = attrValue.split(",");
int width = __ToFloat(arr[0]);
int height = __ToFloat(arr[1]);
this->SetFixedSize(Size(width, height));
}
break;
}
if (attrName == "rect" && !attrValue.empty()) {
auto rectStr = attrValue.split(",");
Rect rect;
rect.X = __ToFloat(rectStr[0]);
rect.Y = __ToFloat(rectStr[1]);
rect.Width = __ToFloat(rectStr[2]);
rect.Height = __ToFloat(rectStr[3]);
this->SetRect(rect);
break;
}
if (attrName == "visible") {
this->m_bVisible = (attrValue != "false");
break;
}
if (attrName == "tips" || attrName == "title") {
this->SetTips(attrValue);
break;
}
if (attrName == "dock") {
if (attrValue == "fill") {
this->m_dock = DockStyle::Fill; break;
}
if (attrValue == "horizontal") {
this->m_dock = DockStyle::Horizontal; break;
}
if (attrValue == "vertical") {
this->m_dock = DockStyle::Vertical; break;
}
break;
}
if (attrName == "action") {
if (attrValue == "close") {
this->Action = ControlAction::Close; break;
}
if (attrValue == "mini") {
this->Action = ControlAction::Mini; break;
}
if (attrValue == "max") {
this->Action = ControlAction::Max; break;
}
if (attrValue == "title") {
this->Action = ControlAction::Title; break;
}
if (attrValue == "move" || attrValue == "movewindow") {
this->Action = ControlAction::MoveWindow; break;
}
break;
}
if (attrName == "enable") {
if (attrValue == "true") {
this->SetEnabled(true);
break;
}
if (attrValue == "false") {
this->SetEnabled(false);
break;
}
}
if (attrName == "disabled") {
this->SetEnabled(false);
break;
}
if (attrName == "scrollbar") {
ScrollBar* sb = this->GetScrollBar();
if (sb) {
sb->SetAttribute("name", attrValue);
}
break;
}
if (attrName == "event") {
if (attrValue == "none") {
this->SetHitTestVisible(false);
}
break;
}
} while (false);
}
const Controls& Control::GetViewControls()
{
return this->ViewControls;
}
float Control::GetScale()
{
return this->m_scale;
}
HWND Control::Hwnd()
{
return m_hWnd;
}
void Control::SetHwnd(HWND hWnd)
{
m_hWnd = hWnd;
}
int Control::X()
{
return m_rect.X;
}
int Control::Y()
{
return m_rect.Y;
}
int Control::Width()
{
return m_rect.Width;
}
int Control::Height()
{
return m_rect.Height;
}
void Control::SetX(int X) {
SetLocation({ X,m_rect.Y });
}
void Control::SetY(int Y) {
SetLocation({ m_rect.X,Y });
}
void Control::SetLocation(const Point& pt) {
SetRect(Rect(pt.X, pt.Y, m_rect.Width, m_rect.Height));
}
void Control::SetWidth(int width) {
SetSize({ width,m_rect.Height });
}
void Control::SetHeight(int height) {
SetSize({ m_rect.Width,height });
}
void Control::SetSize(const Size& size)
{
SetRect({ m_rect.X,m_rect.Y,size.Width,size.Height });
}
Point Control::GetLocation()
{
return m_rect.GetLocation();
}
Size Control::GetSize()
{
return m_rect.GetSize();
}
const Rect& Control::GetRect()
{
return m_rect;
}
void Control::SetFixedWidth(int fixedWidth)
{
m_fixedSize.Width = fixedWidth;
SetRect({ m_rect.X,m_rect.Y,fixedWidth,m_rect.Height });
}
void Control::SetFixedHeight(int fixedHeight)
{
m_fixedSize.Height = fixedHeight;
SetRect({ m_rect.X,m_rect.Y,m_rect.Width,fixedHeight });
}
void Control::SetRateWidth(float rateWidth)
{
m_rateSize.Width = rateWidth;
if (Parent) {
SetFixedWidth(Parent->Width() * rateWidth);
}
}
void Control::SetRateHeight(float rateHeight)
{
m_rateSize.Height = rateHeight;
if (Parent) {
SetFixedHeight(Parent->Height() * rateHeight);
}
}
void Control::SetFixedSize(const Size& size)
{
m_fixedSize.Width = size.Width;
m_fixedSize.Height = size.Height;
SetRect({ m_rect.X,m_rect.Y,size.Width,size.Height });
}
int Control::GetFixedWidth()
{
if (Parent) {
if (m_rateSize.Width > EZUI_FLOAT_EPSILON) {
m_fixedSize.Width = Parent->Width() * m_rateSize.Width + 0.5;
}
}
return m_fixedSize.Width;
}
int Control::GetFixedHeight()
{
if (Parent) {
if (m_rateSize.Height > EZUI_FLOAT_EPSILON) {
m_fixedSize.Height = Parent->Height() * m_rateSize.Height + 0.5;
}
}
return m_fixedSize.Height;
}
bool Control::IsPendLayout() {
return this->m_layoutState == LayoutState::Pend;
}
const LayoutState Control::TryPendLayout() {
if (this->m_layoutState == LayoutState::None) {
this->m_layoutState = LayoutState::Pend;
}
return this->m_layoutState;
}
const LayoutState Control::GetLayoutState()
{
return this->m_layoutState;
}
void Control::EndLayout() {
this->m_layoutState = LayoutState::None;
}
Rect Control::GetClientRect() {
Control* pCtrl = this;
const Rect& rect = GetRect();
int x = rect.X;
int y = rect.Y;
while ((pCtrl = pCtrl->Parent))
{
x += pCtrl->X();
y += pCtrl->Y();
}
return Rect{ x,y,Width(),Height() };
}
Rect Control::GetScreenRect()
{
RECT winRect{ 0,0,0,0 };
GetWindowRect(Hwnd(), &winRect);//获取外层窗口基于屏幕的坐标
Rect ctrlRect = GetClientRect();//获取当前控件基于客户端窗口的坐标
ctrlRect.X += winRect.left;
ctrlRect.Y += winRect.top;
return ctrlRect;
}
DockStyle Control::GetDockStyle()
{
return this->m_dock;
}
void Control::SetDockStyle(const DockStyle& dockStyle)
{
if (dockStyle != this->m_dock && Parent) {
Parent->TryPendLayout();
}
this->m_dock = dockStyle;
}
const Rect& Control::SetRect(const Rect& rect)
{
this->m_rect = rect;
if (GetFixedWidth() > 0) {
m_rect.Width = GetFixedWidth();
}
if (GetFixedHeight() > 0) {
m_rect.Height = GetFixedHeight();
}
Point newLocation = m_rect.GetLocation();
Size newSize = m_rect.GetSize();
if (!m_lastLocation.Equals(newLocation)) {
this->SendEvent(MoveEventArgs(newLocation));
m_lastLocation = newLocation;
}
if (!newSize.Equals(m_lastSize)) {
this->SendEvent(SizeEventArgs(newSize));
m_lastSize = newSize;
}
return this->m_rect;
}
void Control::SetTips(const UIString& text)
{
m_tipsText = text;
}
const UIString& Control::GetTips()
{
return m_tipsText;
}
void Control::RefreshLayout()
{
if (this->m_layoutState == LayoutState::Layouting) {
return;
}
this->m_layoutState = LayoutState::Layouting;//布局中
if (GetScrollBar()) {//如果存在滚动条就设置滚动条的矩形位置
GetScrollBar()->ParentSize({ m_rect.Width,m_rect.Height });
}
m_contentSize.Width = 0;
m_contentSize.Height = 0;
this->OnLayout();
if (IsAutoHeight() && Height() != m_contentSize.Height) {
this->SetFixedHeight(m_contentSize.Height);
this->EndLayout();
this->RefreshLayout();
if (Parent) {
Parent->RefreshLayout();
Parent->Invalidate();
}
return;
}
if (IsAutoWidth() && Width() != m_contentSize.Width) {
this->SetFixedWidth(m_contentSize.Width);
this->EndLayout();
this->RefreshLayout();
if (Parent) {
Parent->RefreshLayout();
Parent->Invalidate();
}
return;
}
this->EndLayout();
}
void Control::OnLayout() {
m_contentSize.Width = 0;
m_contentSize.Height = 0;
int _width;
int _height;
for (auto& it : GetControls()) {
if (Parent) {
//设置了宽高百分比的控件
if (it->m_rateSize.Width > EZUI_FLOAT_EPSILON) {
it->SetFixedWidth(Parent->Width() * it->m_rateSize.Width);
}
if (it->m_rateSize.Height > EZUI_FLOAT_EPSILON) {
it->SetFixedHeight(Parent->Height() * it->m_rateSize.Height);
}
}
//设置了dockstyle的控件
if (it->GetDockStyle() == DockStyle::Fill) {
it->SetRect(Rect{ 0,0,Width(),Height() });
}
else if (it->GetDockStyle() == DockStyle::Vertical) {
it->SetRect(Rect{ it->X(),0,it->Width(),Height() });
}
else if (it->GetDockStyle() == DockStyle::Horizontal) {
it->SetRect(Rect{ 0,it->Y(),Width(),it->Height() });
}
_width = it->X() + it->Width();
if (_width > m_contentSize.Width) {
m_contentSize.Width = _width;
}
_height = it->Y() + it->Height();
if (_height > m_contentSize.Height) {
m_contentSize.Height = _height;
}
}
this->EndLayout();
}
void Control::SendEvent(const EventArgs& arg)
{
this->OnEvent((EventArgs&)arg);
}
void Control::OnEvent(EventArgs& arg)
{
if (!this->IsEnabled() && ((arg.EventType & Event::OnMouseEvent) == arg.EventType || (arg.EventType & Event::OnKeyBoardEvent) == arg.EventType))
{
// 禁用状态下拦截鼠标或键盘事件
return;
}
bool isRemove = false;
this->m_bRemove = &isRemove;
do
{
if (arg.EventType == Event::OnPaint) {
if (IsVisible()) {
this->OnPaintBefore((PaintEventArgs&)arg);
}
return; //绘制消息特殊直接return
}
if (arg.EventType == Event::OnMove) {
this->OnMove((MoveEventArgs&)arg);
break;
}
if (arg.EventType == Event::OnSize) {
this->OnSize((SizeEventArgs&)arg);
break;
}
if (arg.EventType == Event::OnDpiChange) {
this->OnDpiChange((DpiChangeEventArgs&)arg);
break;
}
if ((arg.EventType & Event::OnMouseEvent) == arg.EventType) {
this->OnMouseEvent((MouseEventArgs&)arg);
break;
}
if ((arg.EventType & Event::OnKeyBoardEvent) == arg.EventType) {
this->OnKeyBoardEvent((KeyboardEventArgs&)arg);
break;
}
if (arg.EventType == Event::OnFocus) {
this->OnFocus((FocusEventArgs&)arg);
break;
}
if (arg.EventType == Event::OnKillFocus) {
this->OnKillFocus((KillFocusEventArgs&)arg);
break;
}
} while (false);
do
{
if (isRemove) break;//控件已被删除 不在继续下发通知
//发送给控件自身事件处理器(如果用户绑定了此回调函数,则不再进入主窗口的OnNotify函数)
if (this->EventHandler) {
this->EventHandler(this, arg);
if (isRemove) break;
}
if ((this->NotifyFlags & arg.EventType) == arg.EventType) {
//向Frame层通知事件
IFrame* frame = this->GetFrame();
if (frame) {
frame->OnNotify(this, arg);
}
}
} while (false);
if (!isRemove) {
this->m_bRemove = NULL;
};
}
bool Control::ApplyStyleProperty(const UIString& key, const UIString& value) {
do
{
if (key == "x") {
this->SetLocation({ (int)__ToFloat(value) ,this->Y() });
break;
}
if (key == "y") {
this->SetLocation({ this->X(),(int)__ToFloat(value) });
break;
}
if (key == "width") {
if (value == "auto") {
this->SetAutoWidth(true);//自动宽度
}
else {
if (value.rfind("%") != std::string::npos) {
this->SetRateWidth(__ToFloat(value));//基于父控件的百分比
}
else {
this->SetFixedWidth(__ToFloat(value));//如果单独设置了宽高那就是绝对宽高了
}
}
break;
}
if (key == "height") {
if (value == "auto") {
this->SetAutoHeight(true);//自动高度
}
else {
if (value.rfind("%") != std::string::npos) {
this->SetRateHeight(__ToFloat(value));//基于父控件的百分比
}
else {
this->SetFixedHeight(__ToFloat(value));//如果单独设置了宽高那就是绝对宽高了
}
}
break;
}
if (key == "margin-left") {
this->Margin.Left = __ToFloat(value);
break;
}
if (key == "margin-top") {
this->Margin.Top = __ToFloat(value);
break;
}
if (key == "margin-right") {
this->Margin.Right = __ToFloat(value);
break;
}
if (key == "margin-bottom") {
this->Margin.Bottom = __ToFloat(value);
break;
}
if (key == "margin") {//遵循web前端的规则
auto strs = value.replace(' ', ',').split(",");//去掉空格并转为数组
if (strs.size() == 1) {
this->Margin = __ToFloat(strs[0]);
break;
}
if (strs.size() == 2) {
this->Margin.Top = this->Margin.Bottom = __ToFloat(strs[0]);
this->Margin.Left = this->Margin.Right = __ToFloat(strs[1]);
break;
}
if (strs.size() == 4) {
this->Margin.Top = __ToFloat(strs[0]);
this->Margin.Right = __ToFloat(strs[1]);
this->Margin.Bottom = __ToFloat(strs[2]);
this->Margin.Left = __ToFloat(strs[3]);
break;
}
break;
}
if (key == "display") {
this->m_bVisible = (value != "none");
break;
}
return false;//未处理
} while (false);
return true;//处理成功
}
//专门处理键盘消息的
void Control::OnKeyBoardEvent(const KeyboardEventArgs& _args) {
do
{
KeyboardEventArgs& args = (KeyboardEventArgs&)_args;
switch (args.EventType)
{
case Event::OnKeyChar: {
OnKeyChar(args);
break;
}
case Event::OnKeyDown: {
OnKeyDown(args);
break;
}
case Event::OnKeyUp: {
OnKeyUp(args);
break;
}
default:
break;
}
} while (false);
}
//专门处理鼠标消息的
void Control::OnMouseEvent(const MouseEventArgs& _args) {
MouseEventArgs& args = (MouseEventArgs&)_args;
do
{
switch (args.EventType)
{
case Event::OnMouseWheel: {
OnMouseWheel(args);
break;
}
case Event::OnMouseEnter: {
this->State = ControlState::Hover;
OnMouseEnter(args);
break;
}
case Event::OnMouseMove: {
OnMouseMove(args);
break;
}
case Event::OnMouseDoubleClick: {
OnMouseDoubleClick(args);
break;
}
case Event::OnMouseDown: {
this->m_pressed = true;
this->State = ControlState::Active;
OnMouseDown(args);
break;
}
case Event::OnMouseUp: {
this->m_pressed = false;
OnMouseUp(args);
break;
}
case Event::OnMouseLeave: {
this->m_pressed = false;
this->State = ControlState::Static;
OnMouseLeave(args);
break;
}
default:
break;
}
} while (false);
}
void Control::OnPaintBefore(PaintEventArgs& args) {
this->SetHwnd(args.HWND);
if (this->IsPendLayout()) {//绘制的时候会检查时候有挂起的布局 如果有 立即让布局生效并重置布局标志
this->RefreshLayout();
}
auto clientRect = this->GetClientRect();//获取基于窗口的位置
if (clientRect.IsEmptyArea()) { return; }
auto& invalidRect = args.InvalidRectangle;
auto& pt = args.Graphics;
Rect _ClipRect = clientRect;
this->ComputeClipRect();//重新计算基于父亲的裁剪区域
if (!Rect::Intersect(_ClipRect, this->m_viewRect, invalidRect)) {//和重绘区域进行裁剪
return;
}
//绘制数量+1
++args.PublicData->PaintCount;
//设置绘制偏移 以及旋转
args.PushOffset({ clientRect.X ,clientRect.Y });
float angle = this->GetAngle();
if (angle != 0) {//围绕着控件中心点旋转
float pointX = clientRect.X + clientRect.Width / 2.0f;
float pointY = clientRect.Y + clientRect.Height / 2.0f;
pt.SetTransform(pointX, pointY, angle);
}
//border信息
Border border;
border.Left = GetBorderLeft();
border.Top = GetBorderTop();
border.Right = GetBorderRight();
border.Bottom = GetBorderBottom();
border.TopLeftRadius = GetBorderTopLeftRadius();
border.TopRightRadius = GetBorderTopRightRadius();
border.BottomRightRadius = GetBorderBottomRightRadius();
border.BottomLeftRadius = GetBorderBottomLeftRadius();
bool hasRadius = border.TopLeftRadius || border.TopRightRadius || border.BottomRightRadius || border.BottomLeftRadius;
#if USED_DIRECT2D
if (hasRadius) {
//处理圆角控件 使用纹理的方式 (这样做是为了控件内部无论怎么绘制都不会超出圆角部分) 带抗锯齿
RectangleGeometry roundRect(Rect(0, 0, clientRect.Width, clientRect.Height), border.TopLeftRadius, border.TopRightRadius, border.BottomRightRadius, border.BottomLeftRadius);
RectangleGeometry _clientRect(_ClipRect.X - clientRect.X, _ClipRect.Y - clientRect.Y, _ClipRect.Width, _ClipRect.Height);
Geometry outClipRect;
Geometry::Intersect(outClipRect, roundRect, _clientRect);
args.PushLayer(outClipRect);
}
else {
//针对矩形控件
args.PushLayer(Rect(_ClipRect.X - clientRect.X, _ClipRect.Y - clientRect.Y, _ClipRect.Width, _ClipRect.Height));
}
#endif
this->OnPaint(args);
//通知到主窗口OnNotify或者IFrame的OnNotify函数中
WindowData* publicData = NULL;
if ((this->NotifyFlags & Event::OnPaint) == Event::OnPaint) {
//向Frame层通知事件
IFrame* frame = this->GetFrame();
if (frame) {
frame->OnNotify(this, args);
}
}
//通知到自身控件的处理器
if (this->EventHandler) {
this->EventHandler(this, args);
}
//绘制子控件
this->OnChildPaint(args);
//绘制滚动条
ScrollBar* scrollbar = NULL;
if (scrollbar = this->GetScrollBar()) {
scrollbar->SendEvent(args);
}
//绘制边框
border.Color = GetBorderColor();
border.Style = GetBorderStyle();
this->OnBorderPaint(args, border);//绘制边框
args.PopLayer();//弹出纹理层
#ifdef _DEBUG
if ((publicData = this->GetPublicData()) && publicData->Debug) {
float width = 1 * this->GetScale();
Color color = publicData->DebugColor;
color.SetA(127);
pt.SetColor(color);
//绘制虚线
pt.SetStrokeStyle(StrokeStyle::Dash);
//绘制出控件边框
pt.DrawRectangle(RectF(0, 0, clientRect.Width, clientRect.Height), 0, width);
//绘制出边距 类似安卓那样显示
// 左边距
if (Margin.Left) {
pt.FillRectangle(RectF(0 - Margin.Left, 0, Margin.Left, clientRect.Height));
}
// 上边距
if (Margin.Top) {
pt.FillRectangle(RectF(0, 0 - Margin.Top, clientRect.Width, Margin.Top));
}
// 右边距
if (Margin.Right) {
pt.FillRectangle(RectF(clientRect.Width, 0, Margin.Right, clientRect.Height));
}
// 下边距
if (Margin.Bottom) {
pt.FillRectangle(RectF(0, clientRect.Height, clientRect.Width, Margin.Bottom));
}
}
#endif
args.PopOffset();//弹出偏移
if (angle != 0) {
pt.SetTransform(0, 0, 0);
}
}
void Control::OnDpiChange(const DpiChangeEventArgs& arg)
{
float scale = arg.Scale / this->m_scale;
this->m_scale = arg.Scale;
bool needScale = false;
if (!IsFloatEqual(scale, 1.0f)) {
needScale = true;
int fw = this->GetFixedWidth() * scale + 0.5;
int fh = this->GetFixedHeight() * scale + 0.5;
if (fw && fh) {
this->SetFixedSize(Size(fw, fh));
}
else if (fw) {
this->SetFixedWidth(fw);
}
else if (fh) {
this->SetFixedHeight(fh);
}
Rect newRect = GetRect();
this->SetRect(newRect.Scale(scale));
this->Margin.Scale(scale);
this->Style.Scale(scale);
this->ActiveStyle.Scale(scale);
this->HoverStyle.Scale(scale);
this->DisabledStyle.Scale(scale);
}
for (auto& it : GetControls()) {
it->SendEvent(arg);
}
if (needScale && this->GetScrollBar()) {
this->GetScrollBar()->SendEvent(arg);
}
}
Control::~Control()
{
auto* publicData = GetPublicData();
//清除绑定信息
if (publicData) {
publicData->CleanControl(this);
}
}
Image* Control::Attach(Image* img)
{
m_imgs.Add(img);
return img;
}
void Control::Detach(Image* img)
{
m_imgs.Remove(img);
}
int Control::IndexOf(Control* childCtl)
{
const auto& pControls = this->GetControls();
int pos = 0;
for (auto itor = pControls.begin(); itor != pControls.end(); ++itor)
{
if (dynamic_cast<Spacer*>(*itor)) {
continue;
}
if ((*itor) == childCtl) {
return pos;
}
++pos;
}
return -1;
}
Control* Control::Add(Control* ctl) {
#ifdef _DEBUG
auto itor = std::find(m_controls.begin(), m_controls.end(), ctl);
if (itor != m_controls.end()) {
ASSERT(!"The control already exists and cannot be added repeatedly");
}
#endif
if (dynamic_cast<Spacer*>(ctl)) {
this->Attach(ctl);
}
m_controls.push_back(ctl);
ctl->SetHwnd(this->Hwnd());
ctl->Parent = this;
if (ctl->GetScale() != this->GetScale()) {
ctl->SendEvent(DpiChangeEventArgs(this->GetScale()));
}
ctl->TryPendLayout();
this->TryPendLayout();//添加控件需要将布局重新挂起
return ctl;
}
void Control::Insert(int pos, Control* ctl)
{
#ifdef _DEBUG
{
auto itor = std::find(m_controls.begin(), m_controls.end(), ctl);
if (itor != m_controls.end()) {
ASSERT(!"The control already exists and cannot be added repeatedly");
}
}
#endif
if (dynamic_cast<Spacer*>(ctl)) {
this->Attach(ctl);
}
size_t i = 0;
auto itor = m_controls.begin();
for (; itor != m_controls.end(); ++itor) {
if (i == pos) {
break;
}
++i;
}
if (itor == m_controls.end()) {
m_controls.push_back(ctl);
}
else {
m_controls.insert(itor, ctl);
}
ctl->SetHwnd(this->Hwnd());
ctl->Parent = this;
if (ctl->GetScale() != this->GetScale()) {
ctl->SendEvent(DpiChangeEventArgs(this->GetScale()));
}
ctl->TryPendLayout();
this->TryPendLayout();//添加控件需要将布局重新挂起
}
void Control::SetParent(Control* parentCtl)
{
parentCtl->Add(this);
}
void Control::Remove(Control* ctl, bool freeCtrl)
{
//寻找控件看是否包含
auto itor = ::std::find(m_controls.begin(), m_controls.end(), ctl);
if (itor != m_controls.end()) {
ctl->OnRemove();
this->TryPendLayout();//移除控件需要将布局重新挂起
m_controls.erase(itor);
auto itor2 = ::std::find(ViewControls.begin(), ViewControls.end(), ctl);
if (itor2 != ViewControls.end()) {
ViewControls.erase(itor2);
}
if (freeCtrl) {
delete ctl;
}
}
//子对象存在相同的对象也要跟随移除
this->Detach(ctl);
}
void Control::OnRemove()
{
if (m_bRemove) {
*m_bRemove = true;
}
for (auto& it : m_controls) {
it->OnRemove();
}
auto* publicData = GetPublicData();
if (publicData) {
publicData->CleanControl(this);
}
}
Control* Control::FindControl(const UIString& ctlName)
{
if (ctlName.empty()) {
return NULL;
}
if (this->Name == ctlName) {
return this;
}
for (auto& it : (this->m_controls))
{
if (it->Name == ctlName) {
return it;
}
if (dynamic_cast<IFrame*>(it)) {
continue;//对IFrame内的控件进行隔离
}
auto ctl = it->FindControl(ctlName);
if (ctl) return ctl;
}
return NULL;
}
Controls Control::FindControl(const UIString& attrName, const UIString& attrValue)
{
Controls ctls;
if (attrName.empty() || attrValue.empty()) {
return ctls;
}
for (auto& it : (this->m_controls))
{
if (it->GetAttribute(attrName) == attrValue) {
ctls.push_back(it);
}
if (dynamic_cast<IFrame*>(it)) {
continue;//对IFrame内的控件进行隔离
}
auto _ctls = it->FindControl(attrName, attrValue);
for (auto& it2 : _ctls) {
ctls.push_back(it2);
}
}
return ctls;
}
Control* Control::FindSingleControl(const UIString& attrName, const UIString& attrValue) {
auto list = this->FindControl(attrName, attrValue);
if (list.size() > 0) {
return *list.begin();
}
return NULL;
}
Control* Control::FindChild(const UIString& ctlName)
{
if (ctlName.empty()) {
return NULL;
}
for (auto& it : (this->m_controls))
{
if (it->Name == ctlName) {
return it;
}
}
return NULL;
}
Controls Control::FindChild(const UIString& attrName, const UIString& attrValue)
{
Controls ctls;
if (attrName.empty() || attrValue.empty()) {
return ctls;
}
for (auto& it : (this->m_controls))
{
if (it->GetAttribute(attrName) == attrValue) {
ctls.push_back(it);
}
}
return ctls;
}
Control* Control::FindSingleChild(const UIString& ctlName, const UIString& attrValue) {
auto list = this->FindChild(ctlName, attrValue);
if (list.size() > 0) {
return *list.begin();
}
return NULL;
}
bool Control::SwapChild(Control* ct1, Control* ct2)
{
int swapCount = 0;
for (auto& it : this->m_controls) {
if (swapCount == 2) {
break;
}
if (it == ct1) {
it = ct2;
++swapCount;
continue;
}
if (it == ct2) {
it = ct1;
++swapCount;
continue;
}
}
if (swapCount == 2) {
this->TryPendLayout();
return true;
}
return false;
}
void Control::SetEnabled(bool flag) {
this->m_enabled = flag;
}
void Control::SetDisabled(bool flag) {
this->m_enabled = !flag;
}
bool Control::IsEnabled() {
return this->m_enabled;
}
void Control::SetVisible(bool flag) {
if (flag != this->m_bVisible && this->Parent) {
this->Parent->TryPendLayout();
}
this->m_bVisible = flag;
}
bool Control::IsVisible() {
return this->m_bVisible;
}
void Control::Hide() {
m_bVisible = false;
this->Invalidate();
}
void Control::Show() {
m_bVisible = true;
this->Invalidate();
}
void Control::SetHitTestVisible(bool bEnable) {
m_hitTestEnabled = bEnable;
}
bool Control::IsHitTestVisible() {
return m_hitTestEnabled;
}
bool Control::Invalidate() {
auto* publicData = GetPublicData();
if (publicData) {
if (Parent && this->IsPendLayout()) {
return Parent->Invalidate();
}
float angle = this->GetAngle();
if (!(angle == 0 || angle == 180) && Parent) {
return Parent->Invalidate();
}
if (publicData) {
Rect _InvalidateRect = GetClientRect();
publicData->InvalidateRect(_InvalidateRect);
return true;
}
}
return false;
}
void Control::Refresh() {
if (Invalidate()) {
auto* publicData = GetPublicData();
if (publicData) {
publicData->Refresh();//立即更新全部无效区域
}
}
}
Rect Control::GetCareRect()
{
return Rect();
}
const Size& Control::GetContentSize()
{
return m_contentSize;
}
bool Control::IsAutoWidth()
{
return this->m_bAutoWidth;
}
void Control::SetAutoSize(bool flag)
{
this->SetAutoWidth(flag);
this->SetAutoHeight(flag);
}
void Control::SetAutoWidth(bool flag)
{
if (flag != this->m_bAutoWidth && Parent) {
Parent->TryPendLayout();
}
if (flag && Width() == 0) {
m_rect.Width = 1;
}
this->m_bAutoWidth = flag;
}
bool Control::IsAutoHeight()
{
return this->m_bAutoHeight;
}
void Control::SetAutoHeight(bool flag)
{
if (flag != this->m_bAutoHeight && Parent) {
Parent->TryPendLayout();
}
if (flag && Height() == 0) {
m_rect.Height = 1;
}
this->m_bAutoHeight = flag;
}
void Control::SetContentWidth(int width)
{
this->m_contentSize.Width = width;
}
void Control::SetContentHeight(int height)
{
this->m_contentSize.Height = height;
}
void Control::SetContentSize(const Size& size)
{
this->m_contentSize = size;
}
void Control::ComputeClipRect()
{
if (Parent) {
Rect& ClipRectRef = *(Rect*)(&this->m_viewRect);//引用父控件的裁剪区域
Rect::Intersect(ClipRectRef, this->GetClientRect(), Parent->m_viewRect);//自身和父控件对比较裁剪区域
}
else {
Rect& ClipRectRef = *(Rect*)(&this->m_viewRect);
ClipRectRef = this->GetClientRect();
}
}
const Controls& Control::GetControls()
{
return m_controls;
}
Control* Control::GetControl(int pos)
{
int _pos = 0;
for (auto& it : m_controls) {
if (_pos == pos) {
return it;
}
++_pos;
}
return NULL;
}
bool Control::Contains(Control* ctl) {
ASSERT(ctl);
Control* pControl = ctl;
while (pControl)
{
if (pControl == this || pControl == this->GetScrollBar()) {
return true;
}
pControl = pControl->Parent;
}
return false;
}
void Control::Clear()
{
this->Clear(false);
}
void Control::Clear(bool freeChilds)
{
auto temp = m_controls;
for (auto itor = temp.begin(); itor != temp.end(); ++itor)
{
Control* it = *itor;
it->OnRemove();
if (freeChilds) {
//子对象存在相同的对象也要跟随移除
this->Detach(it);
delete it;
}
}
this->ViewControls.clear();//清空可见控件
this->m_controls.clear();//清空子控件集合
this->TryPendLayout();//挂起布局
ScrollBar* scrollBar = this->GetScrollBar();
if (scrollBar) {
scrollBar->Reset();
}
}
void Control::OnMouseMove(const MouseEventArgs& args)
{
}
void Control::OnMouseWheel(const MouseEventArgs& args)
{
}
void Control::OnMouseDoubleClick(const MouseEventArgs& args)
{
}
void Control::OnMouseEnter(const MouseEventArgs& args)
{
this->Invalidate();
}
void Control::OnMouseDown(const MouseEventArgs& args)
{
this->Invalidate();
}
void Control::OnMouseUp(const MouseEventArgs& args)
{
this->Invalidate();
}
void Control::OnMouseLeave(const MouseEventArgs& args)
{
this->Invalidate();
}
void Control::OnKeyChar(const KeyboardEventArgs& args) {
}
void Control::OnKeyDown(const KeyboardEventArgs& args) {
}
void Control::OnKeyUp(const KeyboardEventArgs& args) {
}
void Control::OnFocus(const FocusEventArgs& _args)
{
}
void Control::OnKillFocus(const KillFocusEventArgs& arg)
{
}
void Control::OnMove(const MoveEventArgs& arg)
{
}
void Control::OnSize(const SizeEventArgs& arg)
{
this->TryPendLayout();//将自己挂起
if (Parent) {
Parent->TryPendLayout();//将父控件挂起
}
}
ScrollBar* Control::GetScrollBar()
{
return NULL;
}
void Control::SetStyle(ControlStyle& style, const UIString& key, const UIString& value_)
{
UIString value = value_;
do
{
if (this->ApplyStyleProperty(key, value)) {
break;
}
if (key == "pointer-events") {
if (value == "none") {
//忽略鼠标键盘事件 将直接穿透
this->SetHitTestVisible(false);
}
break;
}
if (key == "cursor") {
if (value == "pointer") {
style.Cursor = LoadCursor(ezui::Cursor::HAND);
}
else if (value == "help") {
style.Cursor = LoadCursor(ezui::Cursor::HELP);
}
else if (value == "n-resize") {
//南北箭头 纵向
style.Cursor = LoadCursor(ezui::Cursor::SIZENS);
}
else if (value == "e-resize") {
//东西箭头 水平
style.Cursor = LoadCursor(ezui::Cursor::SIZEWE);
}
else if (value == "move") {
//四个方向的箭头都有
style.Cursor = LoadCursor(ezui::Cursor::SIZEALL);
}
break;
}
if (key == "background-color") {
style.BackColor = Color::Make(value);
break;
}
if (key == "background-image") {
style.BackImage = this->Attach(__MakeImage(value));
break;
}
if (key == "background-position" && style.BackImage) {
if (value.count("px") >= 2) {
auto pxs = value.split(" ");
float x = 0;
__IsPx(pxs[0], x);
style.BackImage->DrawPosition.X = x;
float y = 0;
__IsPx(pxs[1], y);
style.BackImage->DrawPosition.Y = y;
}
break;
}
if (key == "background-size" || key == "background-image-size") {
if (value == "auto" && style.BackImage) {
style.BackImage->SizeMode = ImageSizeMode::Original;
}
else if (value.count("px") >= 2 && style.BackImage) {
auto pxs = value.split(" ");
float w = 0;
__IsPx(pxs[0], w);
style.BackImage->DrawSize.Width = w;
float h = 0;
__IsPx(pxs[1], h);
style.BackImage->DrawSize.Height = h;
}
break;
}
if (key == "fore-image") {
style.ForeImage = this->Attach(__MakeImage(value));
break;
}
if (key == "fore-image-size") {
if (value == "auto" && style.ForeImage) {
style.ForeImage->SizeMode = ImageSizeMode::Original;
}
break;
}
if (key == "color" || key == "fore-color") {
style.ForeColor = Color::Make(value);
break;
}
if (key == "border-color") {
style.Border.Color = Color::Make(value);
break;
}
if (key == "border-style") {
if (value == "solid") {
style.Border.Style = StrokeStyle::Solid;
}
else if (value == "dashed") {
style.Border.Style = StrokeStyle::Dash;
}
break;
}
if (key == "border-radius") {
style.Border.Radius = __ToFloat(value);
break;
}
if (key == "border-top-left-radius") {
style.Border.TopLeftRadius = __ToFloat(value);
break;
}
if (key == "border-top-right-radius") {
style.Border.TopRightRadius = __ToFloat(value);
break;
}
if (key == "border-bottom-right-radius") {
style.Border.BottomRightRadius = __ToFloat(value);
break;
}
if (key == "border-bottom-left-radius") {
style.Border.BottomLeftRadius = __ToFloat(value);
break;
}
if (key == "font-size") {
style.FontSize = __ToFloat(value);
break;
}
if (key == "font-family") {
value = value.replace("\"", "");//删除双引号;
style.FontFamily = value.unicode();
break;
}
if (key == "border-width") {
style.Border = __ToFloat(value);
break;
}
if (key == "border") {
__MakeBorder(value, style.Border, [&style](float num) {
style.Border.Left = num;
style.Border.Top = num;
style.Border.Right = num;
style.Border.Bottom = num;
});
break;
}
if (key == "border-left") {
__MakeBorder(value, style.Border, [&style](float num) {
style.Border.Left = num;
});
break;
}
if (key == "border-top") {
__MakeBorder(value, style.Border, [&style](float num) {
style.Border.Top = num;
});
break;
}
if (key == "border-right") {
__MakeBorder(value, style.Border, [&style](float num) {
style.Border.Right = num;
});
break;
}
if (key == "border-bottom") {
__MakeBorder(value, style.Border, [&style](float num) {
style.Border.Bottom = num;
});
break;
}
} while (false);
}
void Control::SetStyleSheet(ControlState state, const UIString& styleStr)
{
auto attrs = styleStr.split(";");//分割每一行样式
if (!attrs.empty()) {
ControlStyle& sytle = this->GetStyle(state);//获取对应状态下的Style
for (auto& it : attrs) {
size_t pos = it.find(":");
if (pos == std::string::npos) {
continue;
}
UIString key = it.substr(0, pos);
UIString value = it.substr(pos + 1);
key = key.trim();//去除前后空格
value = value.trim();//去除前后空格
this->SetStyle(sytle, key, value);//去应用每一行样式
}
}
}
bool Control::IsPressed()
{
return m_pressed;
}
};